diff --git a/libtpms.spec b/libtpms.spec index b6b41cb4fcb9269dcc1076621795fa40a6629b71..1a4979b8d7811fbc08484304fa7730b9ede1adf6 100644 --- a/libtpms.spec +++ b/libtpms.spec @@ -6,7 +6,7 @@ %define name libtpms %define versionx 0.7.3 -%define release 3 +%define release 8 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" @@ -19,14 +19,28 @@ Summary: Library providing Trusted Platform Module (TPM) functionality Name: %{name} Version: %{versionx} -Release: 3 +Release: %{release} License: BSD Group: Development/Libraries Url: http://github.com/stefanberger/libtpms Source0: %{url}/archive/%{gitcommit}/%{name}-%{gitshortcommit}.tar.gz Provides: libtpms-%{crypto_subsystem} = %{version}-%{release} -Patch0: 0001-tpm2-CryptSym-fix-AES-output-IV.patch +Patch0: tpm2-CryptSym-fix-AES-output-IV.patch +Patch1: tpm2-Add-SEED_COMPAT_LEVEL-to-seeds-in.patch +Patch2: tpm2-Add-SEED_COMPAT_LEVEL-to-nullSeed-to-track-comp.patch +Patch3: tpm2-Add-SEED_COMPAT_LEVEL-to-DRBG-state.patch +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 +Patch11: tpm2-Reset-TPM2B-buffer-sizes-after-test-fails-for-v.patch +Patch12: tpm2-Add-maxSize-parameter-to-TPM2B_Marshal-for-sani.patch +Patch13: tpm2-Restore-original-value-if-unmarsalled-value-was.patch +Patch14: tpm2-Check-size-of-buffer-before-accessing-it-CVE-20.patch %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel @@ -85,11 +99,11 @@ Libtpms header files and documentation. %define _with_openssl --with-openssl %endif -%if %{build_type} == debug +%if "%{build_type}" == "debug" %define _enable_debug --enable-debug %endif -%if %{build_type} == debug +%if "%{build_type}" == "debug" CFLAGS=-O0 %endif ./autogen.sh \ @@ -119,6 +133,30 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %postun -p /sbin/ldconfig %changelog +* Wed May 17 2023 jiangfangjie - 0.7.3-8 +- fix CVE-2023--1018 and CVE-2023-1017 + +* Wed May 18 2022 yezengruan - 0.7.3-7 +- tpm2: Reset TPM2B buffer sizes after test fails for valid buffer size +- tpm2: Add maxSize parameter to TPM2B_Marshal for sanity checks +- tpm2: Restore original value if unmarsalled value was illegal +- fix CVE-2021-3623 + +* Mon Feb 14 2022 imxcc - 0.7.3-6 +- fix bare word "debug" in spec + +* 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 +-SUG:NA +-DESC:fix CVE-2021-3505 + * Mon Apr 5 2021 jiangfangjie - 0.7.3-3 - Type:CVE - ID:NA @@ -126,7 +164,7 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la - DESC: fix CVE-2021-3446 * Mon Sep 14 2020 jiangfangjie - 0.7.3-2 -- update spec file including source0 and update source file +- update spec file including source0 and update source file * Fri Aug 21 2020 jiangfangjie - 0.7.3-1 - Package init diff --git a/tpm2-Activate-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX.patch b/tpm2-Activate-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX.patch new file mode 100644 index 0000000000000000000000000000000000000000..eadcfb9fcd3c2c5e369cedce2ad5d5bf59795071 --- /dev/null +++ b/tpm2-Activate-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX.patch @@ -0,0 +1,52 @@ +From eb36e429ebe6d0dd7e1ca07013245ab766eec02d Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 14:17:54 +0800 +Subject: [PATCH 7/7] tpm2: Activate SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX + +--- + src/tpm2/BackwardsCompatibility.h | 2 +- + src/tpm2/crypto/openssl/CryptPrime.c | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/tpm2/BackwardsCompatibility.h b/src/tpm2/BackwardsCompatibility.h +index ded6936..6d33b60 100644 +--- a/src/tpm2/BackwardsCompatibility.h ++++ b/src/tpm2/BackwardsCompatibility.h +@@ -43,7 +43,7 @@ typedef UINT8 SEED_COMPAT_LEVEL; + enum { + SEED_COMPAT_LEVEL_ORIGINAL = 0, /* original TPM 2 code up to rev155 */ + SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX = 1, /* RsaAdjustPrimeCandidate was fixed */ +- SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_ORIGINAL ++ SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX + }; + + #endif /* BACKWARDS_COMPATIBILITY_H */ +diff --git a/src/tpm2/crypto/openssl/CryptPrime.c b/src/tpm2/crypto/openssl/CryptPrime.c +index 2e8601c..9ffacc2 100644 +--- a/src/tpm2/crypto/openssl/CryptPrime.c ++++ b/src/tpm2/crypto/openssl/CryptPrime.c +@@ -369,8 +369,8 @@ RsaAdjustPrimeCandidate( + case SEED_COMPAT_LEVEL_ORIGINAL: + RsaAdjustPrimeCandidate_PreRev155(prime); + break; +- /* case SEED_COMPAT_LEVEL_LAST: */ +- case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: ++ case SEED_COMPAT_LEVEL_LAST: ++ /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ + RsaAdjustPrimeCandidate_New(prime); + break; + default: +@@ -409,8 +409,8 @@ BnGeneratePrimeForRSA( + if (g_inFailureMode) + return; + break; +- /* case SEED_COMPAT_LEVEL_LAST: */ +- case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: ++ case SEED_COMPAT_LEVEL_LAST: ++ /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ + if(!BnGetRandomBits(prime, bits, rand)) // new + return; + break; +-- +2.21.0.windows.1 + diff --git a/tpm2-Add-SEED_COMPAT_LEVEL-to-DRBG-state.patch b/tpm2-Add-SEED_COMPAT_LEVEL-to-DRBG-state.patch new file mode 100644 index 0000000000000000000000000000000000000000..677522a8d1e382151f74e3432bfa8137126f5e48 --- /dev/null +++ b/tpm2-Add-SEED_COMPAT_LEVEL-to-DRBG-state.patch @@ -0,0 +1,143 @@ +From 8b534099d59ec5e746802dd77680612539945324 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 11:32:08 +0800 +Subject: [PATCH 3/7] tpm2: Add SEED_COMPAT_LEVEL to DRBG state + +Add a SEED_COMPAT_LEVEL to the DRBG state that is associated with the seed +and indicates the seed compatibility level we need to maintain when deriving +RSA keys from seeds. We only need to be able to handle RSA keys derived via +the DRBG state. Other keys, such as symmetric keys, are not affected. Also +RSA keys cannot be derived from a KDR, so the KDF does not need to carry +the SEED_COMPAT_LEVEL. + +All functions that need to pass a value set SEED_COMPAT_LEVEL to +SEED_COMPAT_LEVEL_ORIGINAL (0) for now. +--- + src/tpm2/HierarchyCommands.c | 3 ++- + src/tpm2/ObjectCommands.c | 3 ++- + src/tpm2/crypto/CryptRand.h | 1 + + src/tpm2/crypto/CryptRand_fp.h | 9 ++++++++- + src/tpm2/crypto/openssl/CryptRand.c | 26 +++++++++++++++++++++++++- + 5 files changed, 38 insertions(+), 4 deletions(-) + +diff --git a/src/tpm2/HierarchyCommands.c b/src/tpm2/HierarchyCommands.c +index 776d2e2..e757191 100644 +--- a/src/tpm2/HierarchyCommands.c ++++ b/src/tpm2/HierarchyCommands.c +@@ -103,7 +103,8 @@ TPM2_CreatePrimary( + &HierarchyGetPrimarySeed(in->primaryHandle)->b, + PRIMARY_OBJECT_CREATION, + (TPM2B *)PublicMarshalAndComputeName(publicArea, &name), +- &in->inSensitive.sensitive.data.b); ++ &in->inSensitive.sensitive.data.b, ++ HierarchyGetPrimarySeedCompatLevel(in->primaryHandle)); // libtpms added + newObject->attributes.primary = SET; + if(in->primaryHandle == TPM_RH_ENDORSEMENT) + newObject->attributes.epsHierarchy = SET; +diff --git a/src/tpm2/ObjectCommands.c b/src/tpm2/ObjectCommands.c +index 590a702..26919eb 100644 +--- a/src/tpm2/ObjectCommands.c ++++ b/src/tpm2/ObjectCommands.c +@@ -508,7 +508,8 @@ TPM2_CreateLoaded( + PRIMARY_OBJECT_CREATION, + (TPM2B *)PublicMarshalAndComputeName(publicArea, + &name), +- &in->inSensitive.sensitive.data.b); ++ &in->inSensitive.sensitive.data.b, ++ HierarchyGetPrimarySeedCompatLevel(in->parentHandle)); // libtpms added + } + else + // This is an ordinary object so use the normal random number generator +diff --git a/src/tpm2/crypto/CryptRand.h b/src/tpm2/crypto/CryptRand.h +index 3eaf986..c3947aa 100644 +--- a/src/tpm2/crypto/CryptRand.h ++++ b/src/tpm2/crypto/CryptRand.h +@@ -138,6 +138,7 @@ typedef union + UINT64 reseedCounter; + UINT32 magic; + DRBG_SEED seed; // contains the key and IV for the counter mode DRBG ++ SEED_COMPAT_LEVEL seedCompatLevel; // libtpms added: the compatibility level for keeping backwards compatibility + UINT32 lastValue[4]; // used when the TPM does continuous self-test + // for FIPS compliance of DRBG + } DRBG_STATE, *pDRBG_STATE; +diff --git a/src/tpm2/crypto/CryptRand_fp.h b/src/tpm2/crypto/CryptRand_fp.h +index b10ee3d..9bf9209 100644 +--- a/src/tpm2/crypto/CryptRand_fp.h ++++ b/src/tpm2/crypto/CryptRand_fp.h +@@ -127,7 +127,8 @@ DRBG_InstantiateSeeded( + const TPM2B *seed, // IN: the seed to use + const TPM2B *purpose, // IN: a label for the generation process. + const TPM2B *name, // IN: name of the object +- const TPM2B *additional // IN: additional data ++ const TPM2B *additional, // IN: additional data ++ SEED_COMPAT_LEVEL seedCompatLevel// IN: compatibility level (associated with seed); libtpms added + ); + LIB_EXPORT BOOL + CryptRandStartup( +@@ -143,6 +144,12 @@ DRBG_Generate( + BYTE *random, // OUT: buffer to receive the random values + UINT16 randomSize // IN: the number of bytes to generate + ); ++// libtpms added begin ++LIB_EXPORT SEED_COMPAT_LEVEL ++DRBG_GetSeedCompatLevel( ++ RAND_STATE *state // IN ++ ); ++// libtpms added end + LIB_EXPORT BOOL + DRBG_Instantiate( + DRBG_STATE *drbgState, // OUT: the instantiated value +diff --git a/src/tpm2/crypto/openssl/CryptRand.c b/src/tpm2/crypto/openssl/CryptRand.c +index 118e1c9..e5bca22 100644 +--- a/src/tpm2/crypto/openssl/CryptRand.c ++++ b/src/tpm2/crypto/openssl/CryptRand.c +@@ -589,7 +589,8 @@ DRBG_InstantiateSeeded( + const TPM2B *seed, // IN: the seed to use + const TPM2B *purpose, // IN: a label for the generation process. + const TPM2B *name, // IN: name of the object +- const TPM2B *additional // IN: additional data ++ const TPM2B *additional, // IN: additional data ++ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ) + { + DF_STATE dfState; +@@ -600,6 +601,7 @@ DRBG_InstantiateSeeded( + // Initialize the DRBG state + memset(drbgState, 0, sizeof(DRBG_STATE)); + drbgState->magic = DRBG_MAGIC; ++ drbgState->seedCompatLevel = seedCompatLevel; // libtpms added + // Size all of the values + totalInputSize = (seed != NULL) ? seed->size : 0; + totalInputSize += (purpose != NULL) ? purpose->size : 0; +@@ -655,6 +657,28 @@ CryptRandInit( + #endif + return DRBG_SelfTest(); + } ++// libtpms added begin ++LIB_EXPORT SEED_COMPAT_LEVEL ++DRBG_GetSeedCompatLevel( ++ RAND_STATE *state ++ ) ++{ ++ if(state == NULL) ++ { ++ return SEED_COMPAT_LEVEL_LAST; ++ } ++ else if(state->drbg.magic == DRBG_MAGIC) ++ { ++ DRBG_STATE *drbgState = (DRBG_STATE *)state; ++ ++ return drbgState->seedCompatLevel; ++ } ++ else ++ { ++ return SEED_COMPAT_LEVEL_LAST; ++ } ++}// libtpms added end ++ + /* 10.2.18.5 DRBG_Generate() */ + /* This function generates a random sequence according SP800-90A. If random is not NULL, then + randomSize bytes of random values are generated. If random is NULL or randomSize is zero, then +-- +2.21.0.windows.1 + diff --git a/tpm2-Add-SEED_COMPAT_LEVEL-to-nullSeed-to-track-comp.patch b/tpm2-Add-SEED_COMPAT_LEVEL-to-nullSeed-to-track-comp.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4fedc6d1bc3731b7d390026ffe007858f75ada2 --- /dev/null +++ b/tpm2-Add-SEED_COMPAT_LEVEL-to-nullSeed-to-track-comp.patch @@ -0,0 +1,110 @@ +From 6617eecb7ea815974a1cfc19f60a091f64c7ba30 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 10:34:49 +0800 +Subject: [PATCH 2/7] tpm2: Add SEED_COMPAT_LEVEL to nullSeed to track + compatibility level + +Add SEED_COMPAT_LEVEL to the nullSeed in the state_reset data to track +its compatibility level. We need it for VM suspend and resume. +--- + src/tpm2/Global.h | 1 + + src/tpm2/Hierarchy.c | 3 ++- + src/tpm2/NVMarshal.c | 21 ++++++++++++++++++--- + 3 files changed, 21 insertions(+), 4 deletions(-) + +diff --git a/src/tpm2/Global.h b/src/tpm2/Global.h +index 011aff8..3448de3 100644 +--- a/src/tpm2/Global.h ++++ b/src/tpm2/Global.h +@@ -809,6 +809,7 @@ typedef struct state_reset_data + // the TPM_RH_NULL hierarchy. The + // default reset value is from the RNG. + TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL ++ SEED_COMPAT_LEVEL nullSeedCompatLevel; // libtpms added + // hierarchy. The default reset value + // is from the RNG. + //***************************************************************************** +diff --git a/src/tpm2/Hierarchy.c b/src/tpm2/Hierarchy.c +index 70a3588..e9e6d6d 100644 +--- a/src/tpm2/Hierarchy.c ++++ b/src/tpm2/Hierarchy.c +@@ -154,6 +154,7 @@ HierarchyStartup( + CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer); + gr.nullSeed.t.size = sizeof(gr.nullSeed.t.buffer); + CryptRandomGenerate(gr.nullSeed.t.size, gr.nullSeed.t.buffer); ++ gr.nullSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + } + return; + } +@@ -235,7 +236,7 @@ HierarchyGetPrimarySeedCompatLevel( + return gp.EPSeedCompatLevel; + break; + case TPM_RH_NULL: +- return SEED_COMPAT_LEVEL_LAST; ++ return gr.nullSeedCompatLevel; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 653ef1a..5c1955b 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -1235,7 +1235,7 @@ skip_future_versions: + } + + #define STATE_RESET_DATA_MAGIC 0x01102332 +-#define STATE_RESET_DATA_VERSION 2 ++#define STATE_RESET_DATA_VERSION 3 + + TPM_RC + STATE_RESET_DATA_Unmarshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) +@@ -1326,11 +1326,21 @@ STATE_RESET_DATA_Unmarshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) + #endif + skip_alg_ecc: + ++ /* default values before conditional block */ ++ data->nullSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; ++ + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { +- BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, + "STATE_RESET_DATA", "version 3 or later"); ++ if (rc == TPM_RC_SUCCESS) { ++ rc = SEED_COMPAT_LEVEL_Unmarshal(&gr.nullSeedCompatLevel, ++ buffer, size, "nullSeed"); ++ } ++ ++ BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ "STATE_RESET_DATA", "version 4 or later"); + /* future versions nest-append here */ + } + +@@ -1349,7 +1359,7 @@ STATE_RESET_DATA_Marshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) + + written = NV_HEADER_Marshal(buffer, size, + STATE_RESET_DATA_VERSION, +- STATE_RESET_DATA_MAGIC, 1); ++ STATE_RESET_DATA_MAGIC, 3); + written += TPM2B_PROOF_Marshal(&data->nullProof, buffer, size); + written += TPM2B_Marshal(&data->nullSeed.b, buffer, size); + written += UINT32_Marshal(&data->clearCount, buffer, size); +@@ -1383,9 +1393,14 @@ STATE_RESET_DATA_Marshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) + #endif + BLOCK_SKIP_WRITE_POP(size); + ++ written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); ++ written += SEED_COMPAT_LEVEL_Marshal(&data->nullSeedCompatLevel, ++ buffer, size); ++ + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + ++ BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + + BLOCK_SKIP_WRITE_CHECK; +-- +2.21.0.windows.1 + diff --git a/tpm2-Add-SEED_COMPAT_LEVEL-to-seeds-in.patch b/tpm2-Add-SEED_COMPAT_LEVEL-to-seeds-in.patch new file mode 100644 index 0000000000000000000000000000000000000000..2866f06be249bb2446f23fc92732ccfe66d631b6 --- /dev/null +++ b/tpm2-Add-SEED_COMPAT_LEVEL-to-seeds-in.patch @@ -0,0 +1,346 @@ +From 2833825447cbc0b23c1aa13a15521aa1d0ec0175 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 10:32:16 +0800 +Subject: [PATCH 1/7] tpm2: Add SEED_COMPAT_LEVEL to seeds in PERSISTENT_DATA + +Add a variable seedCompatLevel to the each seed in the PERSISTENT_DATA +that allows us to track the age of the seed. Whenever a new seed +is created the seedCompatLevel is also written and set to the latest +version. This seedCompatLevel then influences the crypto algorithm that +can be used for deriving keys so that previously derived keys +are now still generated in the same way. When the seed is changed +the old keys are all useless and newly derived keys can then use +the new algorithm. + +This patch only sets the variables to the current compatibility +level SEED_COMPAT_LEVEL_ORIGINAL and writes it out as part of the state +file. This makes the state file not downgradeable. +--- + src/Makefile.am | 1 + + src/tpm2/BackwardsCompatibility.h | 48 +++++++++++++++++++++++++ + src/tpm2/Global.h | 5 +++ + src/tpm2/Hierarchy.c | 31 ++++++++++++++++ + src/tpm2/HierarchyCommands.c | 5 +++ + src/tpm2/Hierarchy_fp.h | 6 ++++ + src/tpm2/NVMarshal.c | 59 +++++++++++++++++++++++++++++-- + 7 files changed, 152 insertions(+), 3 deletions(-) + create mode 100644 src/tpm2/BackwardsCompatibility.h + +diff --git a/src/Makefile.am b/src/Makefile.am +index 670afbf..e18ba4d 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -482,6 +482,7 @@ noinst_HEADERS += \ + tpm2/VerifySignature_fp.h \ + tpm2/ZGen_2Phase_fp.h \ + \ ++ tpm2/BackwardsCompatibility.h \ + tpm2/LibtpmsCallbacks.h \ + tpm2/NVMarshal.h \ + tpm2/StateMarshal.h \ +diff --git a/src/tpm2/BackwardsCompatibility.h b/src/tpm2/BackwardsCompatibility.h +new file mode 100644 +index 0000000..aa79763 +--- /dev/null ++++ b/src/tpm2/BackwardsCompatibility.h +@@ -0,0 +1,48 @@ ++/********************************************************************************/ ++/* */ ++/* Backwards compatibility related stuff */ ++/* Written by Stefan Berger */ ++/* IBM Thomas J. Watson Research Center */ ++/* */ ++/* (c) Copyright IBM Corporation 2017,2018. */ ++/* */ ++/* All rights reserved. */ ++/* */ ++/* Redistribution and use in source and binary forms, with or without */ ++/* modification, are permitted provided that the following conditions are */ ++/* met: */ ++/* */ ++/* Redistributions of source code must retain the above copyright notice, */ ++/* this list of conditions and the following disclaimer. */ ++/* */ ++/* Redistributions in binary form must reproduce the above copyright */ ++/* notice, this list of conditions and the following disclaimer in the */ ++/* documentation and/or other materials provided with the distribution. */ ++/* */ ++/* Neither the names of the IBM Corporation nor the names of its */ ++/* contributors may be used to endorse or promote products derived from */ ++/* this software without specific prior written permission. */ ++/* */ ++/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ ++/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ ++/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ ++/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ ++/* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ ++/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ ++/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ ++/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ ++/* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ ++/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ ++/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ++/********************************************************************************/ ++ ++#ifndef BACKWARDS_COMPATIBILITY_H ++#define BACKWARDS_COMPATIBILITY_H ++ ++typedef UINT8 SEED_COMPAT_LEVEL; ++enum { ++ SEED_COMPAT_LEVEL_ORIGINAL = 0, /* original TPM 2 code up to rev155 */ ++ SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_ORIGINAL ++}; ++ ++#endif /* BACKWARDS_COMPATIBILITY_H */ +diff --git a/src/tpm2/Global.h b/src/tpm2/Global.h +index 7a215cb..011aff8 100644 +--- a/src/tpm2/Global.h ++++ b/src/tpm2/Global.h +@@ -76,6 +76,7 @@ _NORMAL_WARNING_LEVEL_ + #undef CONTEXT_SLOT + # define CONTEXT_SLOT UINT8 + #endif ++#include "BackwardsCompatibility.h" // libtpms added + #include "Capabilities.h" + #include "TpmTypes.h" + #include "CommandAttributes.h" +@@ -619,6 +620,10 @@ typedef struct + TPM2B_SEED EPSeed; + TPM2B_SEED SPSeed; + TPM2B_SEED PPSeed; ++ // SEED_COMPAT_LEVELs related to creation time of seeds ++ SEED_COMPAT_LEVEL EPSeedCompatLevel; // libtpms added begin ++ SEED_COMPAT_LEVEL SPSeedCompatLevel; ++ SEED_COMPAT_LEVEL PPSeedCompatLevel; // libtpms added end + // Note there is a nullSeed in the state_reset memory. + // Hierarchy proofs + TPM2B_PROOF phProof; +diff --git a/src/tpm2/Hierarchy.c b/src/tpm2/Hierarchy.c +index 798c037..70a3588 100644 +--- a/src/tpm2/Hierarchy.c ++++ b/src/tpm2/Hierarchy.c +@@ -86,6 +86,9 @@ HierarchyPreInstall_Init( + #endif + CryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer); + CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer); ++ gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added begin ++ gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; ++ gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added end + // Initialize owner, endorsement and lockout authorization + gp.ownerAuth.t.size = 0; + gp.endorsementAuth.t.size = 0; +@@ -109,6 +112,9 @@ HierarchyPreInstall_Init( + NV_SYNC_PERSISTENT(EPSeed); + NV_SYNC_PERSISTENT(SPSeed); + NV_SYNC_PERSISTENT(PPSeed); ++ NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added begin ++ NV_SYNC_PERSISTENT(SPSeedCompatLevel); ++ NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added end + NV_SYNC_PERSISTENT(ownerAuth); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(lockoutAuth); +@@ -211,6 +217,31 @@ HierarchyGetPrimarySeed( + } + return seed; + } ++// libtpms added begin ++SEED_COMPAT_LEVEL ++HierarchyGetPrimarySeedCompatLevel( ++ TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ++ ) ++{ ++ switch(hierarchy) ++ { ++ case TPM_RH_PLATFORM: ++ return gp.PPSeedCompatLevel; ++ break; ++ case TPM_RH_OWNER: ++ return gp.SPSeedCompatLevel; ++ break; ++ case TPM_RH_ENDORSEMENT: ++ return gp.EPSeedCompatLevel; ++ break; ++ case TPM_RH_NULL: ++ return SEED_COMPAT_LEVEL_LAST; ++ default: ++ FAIL(FATAL_ERROR_INTERNAL); ++ break; ++ } ++} ++// libtpms added end + /* 8.3.3.5 HierarchyIsEnabled() */ + /* This function checks to see if a hierarchy is enabled. */ + /* NOTE: The TPM_RH_NULL hierarchy is always enabled. */ +diff --git a/src/tpm2/HierarchyCommands.c b/src/tpm2/HierarchyCommands.c +index 6627e99..776d2e2 100644 +--- a/src/tpm2/HierarchyCommands.c ++++ b/src/tpm2/HierarchyCommands.c +@@ -291,6 +291,7 @@ TPM2_ChangePPS( + // Internal Data Update + // Reset platform hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer); ++ gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create a new phProof value from RNG to prevent the saved platform + // hierarchy contexts being loaded + CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer); +@@ -303,6 +304,7 @@ TPM2_ChangePPS( + NvFlushHierarchy(TPM_RH_PLATFORM); + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(PPSeed); ++ NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added + NV_SYNC_PERSISTENT(phProof); + // Re-initialize PCR policies + #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 +@@ -335,6 +337,7 @@ TPM2_ChangeEPS( + // Internal Data Update + // Reset endorsement hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer); ++ gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create new ehProof value from RNG + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); + // Enable endorsement hierarchy +@@ -352,6 +355,7 @@ TPM2_ChangeEPS( + NvFlushHierarchy(TPM_RH_ENDORSEMENT); + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(EPSeed); ++ NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added + NV_SYNC_PERSISTENT(ehProof); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(endorsementAlg); +@@ -382,6 +386,7 @@ TPM2_Clear( + // Internal Data Update + // Reset storage hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer); ++ gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added + // Create new shProof and ehProof value from RNG + CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer); + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); +diff --git a/src/tpm2/Hierarchy_fp.h b/src/tpm2/Hierarchy_fp.h +index 51c79c0..d6e0a89 100644 +--- a/src/tpm2/Hierarchy_fp.h ++++ b/src/tpm2/Hierarchy_fp.h +@@ -78,6 +78,12 @@ TPM2B_SEED * + HierarchyGetPrimarySeed( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy + ); ++// libtpms added begin ++SEED_COMPAT_LEVEL ++HierarchyGetPrimarySeedCompatLevel( ++ TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ++ ); ++// libtpms added end + BOOL + HierarchyIsEnabled( + TPMI_RH_HIERARCHY hierarchy // IN: hierarchy +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index ec94ebf..653ef1a 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -242,6 +242,29 @@ BOOL_Unmarshal(BOOL *boolean, BYTE **buffer, INT32 *size) + return rc; + } + ++static UINT16 ++SEED_COMPAT_LEVEL_Marshal(SEED_COMPAT_LEVEL *source, ++ BYTE **buffer, INT32 *size) ++{ ++ return UINT8_Marshal((UINT8 *)source, buffer, size); ++} ++ ++static TPM_RC ++SEED_COMPAT_LEVEL_Unmarshal(SEED_COMPAT_LEVEL *source, ++ BYTE **buffer, INT32 *size, ++ const char *name) ++{ ++ TPM_RC rc; ++ ++ rc = UINT8_Unmarshal((UINT8 *)source, buffer, size); ++ if (rc == TPM_RC_SUCCESS && *source > SEED_COMPAT_LEVEL_LAST) { ++ TPMLIB_LogTPM2Error("%s compatLevel '%u' higher than supported '%u'\n", ++ name, *source, SEED_COMPAT_LEVEL_LAST); ++ rc = TPM_RC_BAD_VERSION; ++ } ++ return rc; ++} ++ + static int + TPM2B_Cmp(const TPM2B *t1, const TPM2B *t2) + { +@@ -3690,7 +3713,7 @@ skip_future_versions: + } + + #define PERSISTENT_DATA_MAGIC 0x12213443 +-#define PERSISTENT_DATA_VERSION 3 ++#define PERSISTENT_DATA_VERSION 4 + + static UINT16 + PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) +@@ -3703,7 +3726,7 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) + + written = NV_HEADER_Marshal(buffer, size, + PERSISTENT_DATA_VERSION, +- PERSISTENT_DATA_MAGIC, 1); ++ PERSISTENT_DATA_MAGIC, 4); + written += BOOL_Marshal(&data->disableClear, buffer, size); + written += TPM_ALG_ID_Marshal(&data->ownerAlg, buffer, size); + written += TPM_ALG_ID_Marshal(&data->endorsementAlg, buffer, size); +@@ -3775,9 +3798,18 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) + /* there's a 'shadow' pcrAllocated as well */ + written += TPML_PCR_SELECTION_Marshal(&gp.pcrAllocated, buffer, size); + ++ written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); ++ written += SEED_COMPAT_LEVEL_Marshal(&data->EPSeedCompatLevel, ++ buffer, size); ++ written += SEED_COMPAT_LEVEL_Marshal(&data->SPSeedCompatLevel, ++ buffer, size); ++ written += SEED_COMPAT_LEVEL_Marshal(&data->PPSeedCompatLevel, ++ buffer, size); ++ + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); + /* future versions append below this line */ + ++ BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + BLOCK_SKIP_WRITE_POP(size); + +@@ -3963,6 +3995,11 @@ skip_num_policy_pcr_group: + #endif + } + ++ /* default values before conditional block */ ++ data->EPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; ++ data->SPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; ++ data->PPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; ++ + /* version 2 starts having indicator for next versions that we can skip; + this allows us to downgrade state */ + if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { +@@ -3970,8 +4007,24 @@ skip_num_policy_pcr_group: + "Volatile State", "version 3 or later"); + rc = TPML_PCR_SELECTION_Unmarshal(&shadow.pcrAllocated, buffer, size); + +- BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 4, buffer, size, + "PERSISTENT DATA", "version 4 or later"); ++ ++ if (rc == TPM_RC_SUCCESS) { ++ rc = SEED_COMPAT_LEVEL_Unmarshal(&data->EPSeedCompatLevel, ++ buffer, size, "EPSeed"); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = SEED_COMPAT_LEVEL_Unmarshal(&data->SPSeedCompatLevel, ++ buffer, size, "SPSeed"); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = SEED_COMPAT_LEVEL_Unmarshal(&data->PPSeedCompatLevel, ++ buffer, size, "PPSeed"); ++ } ++ ++ BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ "PERSISTENT DATA", "version 5 or later"); + /* future versions nest-append here */ + } + +-- +2.21.0.windows.1 + diff --git a/tpm2-Add-maxSize-parameter-to-TPM2B_Marshal-for-sani.patch b/tpm2-Add-maxSize-parameter-to-TPM2B_Marshal-for-sani.patch new file mode 100644 index 0000000000000000000000000000000000000000..082de0f6e58c03fc70a94cddb5f59979cc7bfb2c --- /dev/null +++ b/tpm2-Add-maxSize-parameter-to-TPM2B_Marshal-for-sani.patch @@ -0,0 +1,267 @@ +From 4ef9469ef6ba45a8628061d94bd21cee6e29b5e1 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 21 Jun 2021 15:10:14 -0400 +Subject: [PATCH 2/3] tpm2: Add maxSize parameter to TPM2B_Marshal for sanity + checks + +Add maxSize parameter to TPM2B_Marshal and assert on it checking +the size of the data intended to be marshaled versus the maximum +buffer size. + +Signed-off-by: Stefan Berger +--- + src/tpm2/Marshal.c | 38 ++++++++++++++++++++------------------ + src/tpm2/Marshal_fp.h | 2 +- + src/tpm2/NVMarshal.c | 18 +++++++++--------- + 3 files changed, 30 insertions(+), 28 deletions(-) + +diff --git a/src/tpm2/Marshal.c b/src/tpm2/Marshal.c +index f97243e..39e69e4 100644 +--- a/src/tpm2/Marshal.c ++++ b/src/tpm2/Marshal.c +@@ -61,6 +61,7 @@ + + /* rev 136 */ + ++#include // libtpms added + #include + + #include "Tpm.h" +@@ -178,9 +179,10 @@ Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size) + } + + UINT16 +-TPM2B_Marshal(TPM2B *source, BYTE **buffer, INT32 *size) ++TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; ++ assert(source->size <= maxSize); // libtpms added + written += UINT16_Marshal(&(source->size), buffer, size); + written += Array_Marshal(source->buffer, source->size, buffer, size); + return written; +@@ -495,7 +497,7 @@ UINT16 + TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +-written += TPM2B_Marshal(&source->b, buffer, size); ++written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -505,7 +507,7 @@ UINT16 + TPM2B_DATA_Marshal(TPM2B_DATA *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +-written += TPM2B_Marshal(&source->b, buffer, size); ++written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -535,7 +537,7 @@ UINT16 + TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -545,7 +547,7 @@ UINT16 + TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -554,7 +556,7 @@ UINT16 + TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -564,7 +566,7 @@ UINT16 + TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -574,7 +576,7 @@ UINT16 + TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.name), buffer, size); // libtpms changed + return written; + } + +@@ -1111,7 +1113,7 @@ UINT16 + TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.attestationData), buffer, size); // libtpms changed + return written; + } + +@@ -1232,7 +1234,7 @@ UINT16 + TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -1253,7 +1255,7 @@ UINT16 + TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -1613,7 +1615,7 @@ UINT16 + TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -1633,7 +1635,7 @@ UINT16 + TPM2B_PRIVATE_KEY_RSA_Marshal(TPM2B_PRIVATE_KEY_RSA *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -1643,7 +1645,7 @@ UINT16 + TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -1879,7 +1881,7 @@ UINT16 + TPM2B_ENCRYPTED_SECRET_Marshal(TPM2B_ENCRYPTED_SECRET *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.secret), buffer, size); // libtpms changed + return written; + } + +@@ -2090,7 +2092,7 @@ UINT16 + TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +@@ -2100,7 +2102,7 @@ UINT16 + TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.credential), buffer, size); // libtpms changed + return written; + } + +@@ -2157,7 +2159,7 @@ UINT16 + TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed + return written; + } + +diff --git a/src/tpm2/Marshal_fp.h b/src/tpm2/Marshal_fp.h +index 4471695..582cc9e 100644 +--- a/src/tpm2/Marshal_fp.h ++++ b/src/tpm2/Marshal_fp.h +@@ -79,7 +79,7 @@ extern "C" { + UINT16 + Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size); + UINT16 +- TPM2B_Marshal(TPM2B *source, BYTE **buffer, INT32 *size); ++ TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size); // libtpms changed + UINT16 + TPM_KEY_BITS_Marshal(TPM_KEY_BITS *source, BYTE **buffer, INT32 *size); + UINT16 +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 8f77fa2..40be17e 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -278,7 +278,7 @@ UINT16 + TPM2B_PROOF_Marshal(TPM2B_PROOF *source, BYTE **buffer, INT32 *size) + { + UINT16 written = 0; +- written += TPM2B_Marshal(&source->b, buffer, size); ++ written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); + return written; + } + +@@ -1361,7 +1361,7 @@ STATE_RESET_DATA_Marshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) + STATE_RESET_DATA_VERSION, + STATE_RESET_DATA_MAGIC, 3); + written += TPM2B_PROOF_Marshal(&data->nullProof, buffer, size); +- written += TPM2B_Marshal(&data->nullSeed.b, buffer, size); ++ written += TPM2B_Marshal(&data->nullSeed.b, sizeof(data->nullSeed.t.buffer), buffer, size); + written += UINT32_Marshal(&data->clearCount, buffer, size); + written += UINT64_Marshal(&data->objectContextID, buffer, size); + +@@ -2146,7 +2146,7 @@ TPM2B_HASH_BLOCK_Marshal(TPM2B_HASH_BLOCK *data, BYTE **buffer, INT32 *size) + { + UINT16 written; + +- written = TPM2B_Marshal(&data->b, buffer, size); ++ written = TPM2B_Marshal(&data->b, sizeof(data->t.buffer), buffer, size); + + return written; + } +@@ -2950,9 +2950,9 @@ VolatileState_Marshal(BYTE **buffer, INT32 *size) + + /* tie the volatile state to the EP,SP, and PPSeed */ + NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); +- written += TPM2B_Marshal(&pd.EPSeed.b, buffer, size); +- written += TPM2B_Marshal(&pd.SPSeed.b, buffer, size); +- written += TPM2B_Marshal(&pd.PPSeed.b, buffer, size); ++ written += TPM2B_Marshal(&pd.EPSeed.b, sizeof(pd.EPSeed.t.buffer), buffer, size); ++ written += TPM2B_Marshal(&pd.SPSeed.b, sizeof(pd.SPSeed.t.buffer), buffer, size); ++ written += TPM2B_Marshal(&pd.PPSeed.b, sizeof(pd.PPSeed.t.buffer), buffer, size); + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v4 */ + +@@ -3753,9 +3753,9 @@ PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) + written += TPM2B_AUTH_Marshal(&data->ownerAuth, buffer, size); + written += TPM2B_AUTH_Marshal(&data->endorsementAuth, buffer, size); + written += TPM2B_AUTH_Marshal(&data->lockoutAuth, buffer, size); +- written += TPM2B_Marshal(&data->EPSeed.b, buffer, size); +- written += TPM2B_Marshal(&data->SPSeed.b, buffer, size); +- written += TPM2B_Marshal(&data->PPSeed.b, buffer, size); ++ written += TPM2B_Marshal(&data->EPSeed.b, sizeof(data->EPSeed.t.buffer), buffer, size); ++ written += TPM2B_Marshal(&data->SPSeed.b, sizeof(data->SPSeed.t.buffer), buffer, size); ++ written += TPM2B_Marshal(&data->PPSeed.b, sizeof(data->PPSeed.t.buffer), buffer, size); + written += TPM2B_PROOF_Marshal(&data->phProof, buffer, size); + written += TPM2B_PROOF_Marshal(&data->shProof, buffer, size); + written += TPM2B_PROOF_Marshal(&data->ehProof, buffer, size); +-- +2.27.0 + diff --git a/tpm2-Check-size-of-buffer-before-accessing-it-CVE-20.patch b/tpm2-Check-size-of-buffer-before-accessing-it-CVE-20.patch new file mode 100644 index 0000000000000000000000000000000000000000..010c7112e67f9fbc4115356b72d204edb31a06ad --- /dev/null +++ b/tpm2-Check-size-of-buffer-before-accessing-it-CVE-20.patch @@ -0,0 +1,50 @@ +From 9beadbbf256c5d08511b9fc286ab47626039d6db Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 7 Mar 2023 13:18:44 +0800 +Subject: [PATCH] tpm2: Check size of buffer before accessing it (CVE-2023-1017 + & -1018) Check that there are sufficient bytes in the buffer before reading + the cipherSize from it. Also, reduce the bufferSize variable by the number of + bytes that make up the cipherSize to avoid reading and writing bytes beyond + the buffer in subsequent steps that do in-place decryption. + +This fixes CVE-2023-1017 & CVE-2023-1018. + +Signed-off-by: jiangfangjie +--- + src/tpm2/CryptUtil.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/tpm2/CryptUtil.c b/src/tpm2/CryptUtil.c +index 002fde0..9b7d56e 100644 +--- a/src/tpm2/CryptUtil.c ++++ b/src/tpm2/CryptUtil.c +@@ -830,6 +830,10 @@ CryptParameterDecryption( + + sizeof(session->sessionKey.t.buffer))); + TPM2B_HMAC_KEY key; // decryption key + UINT32 cipherSize = 0; // size of cipher text ++ ++ if (leadingSizeInByte > bufferSize) ++ return TPM_RC_INSUFFICIENT; ++ + // Retrieve encrypted data size. + if(leadingSizeInByte == 2) + { +@@ -837,6 +841,7 @@ CryptParameterDecryption( + // data to be decrypted + cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); + buffer = &buffer[2]; // advance the buffer ++ bufferSize -= 2; + } + #ifdef TPM4B + else if(leadingSizeInByte == 4) +@@ -844,6 +849,7 @@ CryptParameterDecryption( + // the leading size is four bytes so get the four byte size field + cipherSize = BYTE_ARRAY_TO_UINT32(buffer); + buffer = &buffer[4]; //advance pointer ++ bufferSize -= 4; + } + #endif + else +-- +2.21.0.windows.1 + diff --git a/0001-tpm2-CryptSym-fix-AES-output-IV.patch b/tpm2-CryptSym-fix-AES-output-IV.patch similarity index 100% rename from 0001-tpm2-CryptSym-fix-AES-output-IV.patch rename to tpm2-CryptSym-fix-AES-output-IV.patch 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-Introduce-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FI.patch b/tpm2-Introduce-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FI.patch new file mode 100644 index 0000000000000000000000000000000000000000..d44a9f97c0ceee034b6ba66cedf0863d147f2f06 --- /dev/null +++ b/tpm2-Introduce-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FI.patch @@ -0,0 +1,25 @@ +From 087e54dcc99a36151677581eda92c321907988d9 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 14:12:37 +0800 +Subject: [PATCH 5/7] tpm2: Introduce SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX + but do not use yet + +--- + src/tpm2/BackwardsCompatibility.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/tpm2/BackwardsCompatibility.h b/src/tpm2/BackwardsCompatibility.h +index aa79763..ded6936 100644 +--- a/src/tpm2/BackwardsCompatibility.h ++++ b/src/tpm2/BackwardsCompatibility.h +@@ -42,6 +42,7 @@ + typedef UINT8 SEED_COMPAT_LEVEL; + enum { + SEED_COMPAT_LEVEL_ORIGINAL = 0, /* original TPM 2 code up to rev155 */ ++ SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX = 1, /* RsaAdjustPrimeCandidate was fixed */ + SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_ORIGINAL + }; + +-- +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 + diff --git a/tpm2-Pass-SEED_COMPAT_LEVEL-to-CryptAdjustPrimeCandi.patch b/tpm2-Pass-SEED_COMPAT_LEVEL-to-CryptAdjustPrimeCandi.patch new file mode 100644 index 0000000000000000000000000000000000000000..195f1f547533849441fffebf8a2348dc571fed38 --- /dev/null +++ b/tpm2-Pass-SEED_COMPAT_LEVEL-to-CryptAdjustPrimeCandi.patch @@ -0,0 +1,85 @@ +From 5ffbddedaedc3215da219d35dc3f95b1c52ef393 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 14:15:09 +0800 +Subject: [PATCH 6/7] tpm2: Pass SEED_COMPAT_LEVEL to CryptAdjustPrimeCandidate + function + +Pass the SEED_COMPAT_LEVEL, originating from the seed that's being used, +to the CryptAdjustPrimeCandidate function and use it to determine +whether the old code should be used or the new one. +--- + src/tpm2/crypto/CryptPrime_fp.h | 3 ++- + src/tpm2/crypto/openssl/CryptPrime.c | 26 ++++++++++++++++++++------ + 2 files changed, 22 insertions(+), 7 deletions(-) + +diff --git a/src/tpm2/crypto/CryptPrime_fp.h b/src/tpm2/crypto/CryptPrime_fp.h +index 8cd23f5..e8ac8b8 100644 +--- a/src/tpm2/crypto/CryptPrime_fp.h ++++ b/src/tpm2/crypto/CryptPrime_fp.h +@@ -89,7 +89,8 @@ RsaCheckPrime( + ); + LIB_EXPORT void + RsaAdjustPrimeCandidate( +- bigNum prime ++ bigNum prime, ++ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ); + void + BnGeneratePrimeForRSA( +diff --git a/src/tpm2/crypto/openssl/CryptPrime.c b/src/tpm2/crypto/openssl/CryptPrime.c +index 9a5ee7d..2e8601c 100644 +--- a/src/tpm2/crypto/openssl/CryptPrime.c ++++ b/src/tpm2/crypto/openssl/CryptPrime.c +@@ -361,13 +361,21 @@ RsaAdjustPrimeCandidate_New( + } + LIB_EXPORT void + RsaAdjustPrimeCandidate( +- bigNum prime ++ bigNum prime, ++ SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added + ) + { +- if (1) ++ switch (seedCompatLevel) { ++ case SEED_COMPAT_LEVEL_ORIGINAL: + RsaAdjustPrimeCandidate_PreRev155(prime); +- else ++ break; ++ /* case SEED_COMPAT_LEVEL_LAST: */ ++ case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: + RsaAdjustPrimeCandidate_New(prime); ++ break; ++ default: ++ FAIL(FATAL_ERROR_INTERNAL); ++ } + } + /* 10.2.14.1.8 BnGeneratePrimeForRSA() */ + +@@ -395,15 +403,21 @@ BnGeneratePrimeForRSA( + // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old + // if(g_inFailureMode) // old + // libtpms changed begin +- if (1) { ++ switch (DRBG_GetSeedCompatLevel(rand)) { ++ case SEED_COMPAT_LEVEL_ORIGINAL: + DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits)); + if (g_inFailureMode) + return; +- } else { ++ break; ++ /* case SEED_COMPAT_LEVEL_LAST: */ ++ case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: + if(!BnGetRandomBits(prime, bits, rand)) // new + return; ++ break; ++ default: ++ FAIL(FATAL_ERROR_INTERNAL); + } +- RsaAdjustPrimeCandidate(prime); ++ RsaAdjustPrimeCandidate(prime, DRBG_GetSeedCompatLevel(rand)); + // libtpms changed end + found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS; + } +-- +2.21.0.windows.1 + diff --git a/tpm2-Reset-TPM2B-buffer-sizes-after-test-fails-for-v.patch b/tpm2-Reset-TPM2B-buffer-sizes-after-test-fails-for-v.patch new file mode 100644 index 0000000000000000000000000000000000000000..4a6aaef02427fc125eba602aeaf675bc8cf27b71 --- /dev/null +++ b/tpm2-Reset-TPM2B-buffer-sizes-after-test-fails-for-v.patch @@ -0,0 +1,202 @@ +From aa4f8ee9f23e2a87f704ef1b81de12594480de96 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 21 Jun 2021 14:04:34 -0400 +Subject: [PATCH 1/3] tpm2: Reset TPM2B buffer sizes after test fails for valid + buffer size + +Reset the buffer size indicator in a TPM2B type of buffer after it failed +the test for the maximum buffer size it allows. This prevents having bad +buffer sizes in memory that can come to haunt us when writing the volatile +state for example. + +Signed-off-by: Stefan Berger +--- + src/tpm2/NVMarshal.c | 1 + + src/tpm2/Unmarshal.c | 21 +++++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 7c140ea..8f77fa2 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -1473,6 +1473,7 @@ bn_prime_t_Unmarshal(bn_prime_t *data, BYTE **buffer, INT32 *size) + "allocated %zu\n", + (size_t)data->size, (size_t)data->allocated); + rc = TPM_RC_SIZE; ++ data->size = 0; + } + } + +diff --git a/src/tpm2/Unmarshal.c b/src/tpm2/Unmarshal.c +index 9a1d723..bac7d76 100644 +--- a/src/tpm2/Unmarshal.c ++++ b/src/tpm2/Unmarshal.c +@@ -137,6 +137,7 @@ TPM2B_Unmarshal(TPM2B *target, UINT16 targetSize, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->size > targetSize) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -1617,6 +1618,7 @@ TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION *target, BYTE **buffer, INT32 *s + if ((target->sizeofSelect < PCR_SELECT_MIN) || + (target->sizeofSelect > PCR_SELECT_MAX)) { + rc = TPM_RC_VALUE; ++ target->sizeofSelect = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -1787,6 +1789,7 @@ TPML_CC_Unmarshal(TPML_CC *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_CC) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1824,6 +1827,7 @@ TPML_CCA_Unmarshal(TPML_CCA *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_CC) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1846,6 +1850,7 @@ TPML_ALG_Unmarshal(TPML_ALG *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_ALG_LIST_SIZE) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1868,6 +1873,7 @@ TPML_HANDLE_Unmarshal(TPML_HANDLE *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_HANDLES) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1895,11 +1901,13 @@ TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size) + /* TPM side is hard coded to 2 minimum */ + if (target->count < 2) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { + if (target->count > 8) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1922,6 +1930,7 @@ TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES *target, BYTE **buffer, INT32 *s + if (rc == TPM_RC_SUCCESS) { + if (target->count > HASH_COUNT) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1944,6 +1953,7 @@ TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION *target, BYTE **buffer, INT32 *s + if (rc == TPM_RC_SUCCESS) { + if (target->count > HASH_COUNT) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1967,6 +1977,7 @@ TPML_ALG_PROPERTY_Unmarshal(TPML_ALG_PROPERTY *target, BYTE **buffer, INT32 *siz + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_CAP_ALGS) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -1989,6 +2000,7 @@ TPML_TAGGED_TPM_PROPERTY_Unmarshal(TPML_TAGGED_TPM_PROPERTY *target, BYTE **buf + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_TPM_PROPERTIES) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -2011,6 +2023,7 @@ TPML_TAGGED_PCR_PROPERTY_Unmarshal(TPML_TAGGED_PCR_PROPERTY *target, BYTE **buff + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_PCR_PROPERTIES) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -2033,6 +2046,7 @@ TPML_ECC_CURVE_Unmarshal(TPML_ECC_CURVE *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_ECC_CURVES) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -2055,6 +2069,7 @@ TPML_TAGGED_POLICY_Unmarshal(TPML_TAGGED_POLICY *target, BYTE **buffer, INT32 *s + if (rc == TPM_RC_SUCCESS) { + if (target->count > MAX_TAGGED_POLICIES) { + rc = TPM_RC_SIZE; ++ target->count = 0; // libtpms added + } + } + for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { +@@ -2704,6 +2719,7 @@ TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + return rc; +@@ -3462,6 +3478,7 @@ TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + return rc; +@@ -3985,6 +4002,7 @@ TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL al + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + return rc; +@@ -4080,6 +4098,7 @@ TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + } +@@ -4155,6 +4174,7 @@ TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->dataSize > MAX_NV_INDEX_SIZE) { + rc = TPM_RC_SIZE; ++ target->dataSize = 0; // libtpms added + } + } + return rc; +@@ -4185,6 +4205,7 @@ TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->size != startSize - *size) { + rc = TPM_RC_SIZE; ++ target->size = 0; // libtpms added + } + } + return rc; +-- +2.27.0 + diff --git a/tpm2-Restore-original-value-if-unmarsalled-value-was.patch b/tpm2-Restore-original-value-if-unmarsalled-value-was.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d15693a5797c50bb2b81d3d586a2073bd93e52c --- /dev/null +++ b/tpm2-Restore-original-value-if-unmarsalled-value-was.patch @@ -0,0 +1,998 @@ +From 1e19a2a17ba3256ca67f53b07515dfcc1af9bcc8 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Wed, 18 May 2022 15:33:05 +0800 +Subject: [PATCH 3/3] tpm2: Restore original value if unmarsalled value was + illegal + +Restore the original value of the memory location where data from +a stream was unmarshalled and the unmarshalled value was found to +be illegal. The goal is to not keep illegal values in memory. + +Signed-off-by: Stefan Berger +--- + src/tpm2/Unmarshal.c | 122 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 122 insertions(+) + +diff --git a/src/tpm2/Unmarshal.c b/src/tpm2/Unmarshal.c +index bac7d76..c839a68 100644 +--- a/src/tpm2/Unmarshal.c ++++ b/src/tpm2/Unmarshal.c +@@ -165,6 +165,7 @@ TPM_RC + TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_GENERATED orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); +@@ -172,6 +173,7 @@ TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target != TPM_GENERATED_VALUE) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -197,6 +199,7 @@ TPM_RC + TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ECC_CURVE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); +@@ -215,6 +218,7 @@ TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_CURVE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -240,6 +244,7 @@ TPM_RC + TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_CLOCK_ADJUST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = INT8_Unmarshal(target, buffer, size); +@@ -256,6 +261,7 @@ TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -267,6 +273,7 @@ TPM_RC + TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_EO orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); +@@ -288,6 +295,7 @@ TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -299,6 +307,7 @@ TPM_RC + TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); +@@ -324,6 +333,7 @@ TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -335,6 +345,7 @@ TPM_RC + TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_SU orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(target, buffer, size); +@@ -346,6 +357,7 @@ TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -357,6 +369,7 @@ TPM_RC + TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_SE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(target, buffer, size); +@@ -369,6 +382,7 @@ TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -380,6 +394,7 @@ TPM_RC + TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_CAP orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal(target, buffer, size); +@@ -400,6 +415,7 @@ TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -450,6 +466,7 @@ TPM_RC + TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMA_ALGORITHM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ +@@ -457,6 +474,7 @@ TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_ALGORITHM_reserved) { + rc = TPM_RC_RESERVED_BITS; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -468,6 +486,7 @@ TPM_RC + TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMA_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ +@@ -475,6 +494,7 @@ TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_OBJECT_reserved) { + rc = TPM_RC_RESERVED_BITS; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -486,6 +506,7 @@ TPM_RC + TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMA_SESSION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal((UINT8 *)target, buffer, size); /* libtpms changed */ +@@ -493,6 +514,7 @@ TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_SESSION_reserved) { + rc = TPM_RC_RESERVED_BITS; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -517,6 +539,7 @@ TPM_RC + TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMA_CC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ +@@ -524,6 +547,7 @@ TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_CC_reserved) { + rc = TPM_RC_RESERVED_BITS; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -535,6 +559,7 @@ TPM_RC + TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_YES_NO orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT8_Unmarshal(target, buffer, size); +@@ -546,6 +571,7 @@ TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -557,6 +583,7 @@ TPM_RC + TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -569,6 +596,7 @@ TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOO + isNotPersistent && + isNotLegalNull) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -580,6 +608,7 @@ TPM_RC + TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_PARENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -598,6 +627,7 @@ TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOO + isNotEndorsement && + isNotLegalNull) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -609,6 +639,7 @@ TPM_RC + TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_PERSISTENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -617,6 +648,7 @@ TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *s + BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); + if (isNotPersistent) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -628,6 +660,7 @@ TPM_RC + TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_ENTITY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -654,6 +687,7 @@ TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOO + isNotAuth && + isNotLegalNull) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -665,6 +699,7 @@ TPM_RC + TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_PCR orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -675,6 +710,7 @@ TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allo + if (isNotPcr && + isNotLegalNull) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -686,6 +722,7 @@ TPM_RC + TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_SH_AUTH_SESSION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -698,6 +735,7 @@ TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT3 + isNotPolicySession && + isNotLegalPwd) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -709,6 +747,7 @@ TPM_RC + TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_SH_HMAC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -717,6 +756,7 @@ TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size) + BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); + if (isNotHmacSession) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -728,6 +768,7 @@ TPM_RC + TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_SH_POLICY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -736,6 +777,7 @@ TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size) + BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); + if (isNotPolicySession) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -747,6 +789,7 @@ TPM_RC + TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_CONTEXT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -759,6 +802,7 @@ TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size) + isNotPolicySession && + isNotTransient) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -770,6 +814,7 @@ TPM_RC + TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_DH_SAVED orig_target = *target; // libtpms added + allowNull = allowNull; + + if (rc == TPM_RC_SUCCESS) { +@@ -787,6 +832,7 @@ TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL + isNotSequenceObject && + isNotTransientStClear) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -798,6 +844,7 @@ TPM_RC + TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_HIERARCHY orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -814,6 +861,7 @@ TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *siz + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -825,6 +873,7 @@ TPM_RC + TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_ENABLES orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -842,6 +891,7 @@ TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, B + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -853,6 +903,7 @@ TPM_RC + TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_HIERARCHY_AUTH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -866,6 +917,7 @@ TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -877,6 +929,7 @@ TPM_RC + TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_PLATFORM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -887,6 +940,7 @@ TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -898,6 +952,7 @@ TPM_RC + TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_ENDORSEMENT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -912,6 +967,7 @@ TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -923,6 +979,7 @@ TPM_RC + TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_PROVISION orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -934,6 +991,7 @@ TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *siz + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -945,6 +1003,7 @@ TPM_RC + TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_CLEAR orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -956,6 +1015,7 @@ TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -967,6 +1027,7 @@ TPM_RC + TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_NV_AUTH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -981,6 +1042,7 @@ TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size) + BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); + if (isNotNv) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + } +@@ -994,6 +1056,7 @@ TPM_RC + TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_LOCKOUT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -1004,6 +1067,7 @@ TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1015,6 +1079,7 @@ TPM_RC + TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RH_NV_INDEX orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_HANDLE_Unmarshal(target, buffer, size); +@@ -1023,6 +1088,7 @@ TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size) + BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); + if (isNotNv) { + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1034,6 +1100,7 @@ TPM_RC + TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_HASH orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1062,6 +1129,7 @@ TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL + } + default: + rc = TPM_RC_HASH; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1073,6 +1141,7 @@ TPM_RC + TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_SYM orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1101,6 +1170,7 @@ TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL al + } + default: + rc = TPM_RC_SYMMETRIC; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1112,6 +1182,7 @@ TPM_RC + TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_SYM_OBJECT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1137,6 +1208,7 @@ TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_SYMMETRIC; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1148,6 +1220,7 @@ TPM_RC + TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_SYM_MODE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1179,6 +1252,7 @@ TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *siz + } + default: + rc = TPM_RC_MODE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1190,6 +1264,7 @@ TPM_RC + TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_KDF orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1215,6 +1290,7 @@ TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL al + } + default: + rc = TPM_RC_KDF; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1226,6 +1302,7 @@ TPM_RC + TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_SIG_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1260,6 +1337,7 @@ TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_SCHEME; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1271,6 +1349,7 @@ TPM_RC + TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ECC_KEY_EXCHANGE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1293,6 +1372,7 @@ TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, IN + } + default: + rc = TPM_RC_SCHEME; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1305,6 +1385,7 @@ TPM_RC + TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ST_COMMAND_TAG orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(target, buffer, size); +@@ -1316,6 +1397,7 @@ TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 + break; + default: + rc = TPM_RC_BAD_TAG; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1327,6 +1409,7 @@ TPM_RC + TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_MAC_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1358,6 +1441,7 @@ TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_SYMMETRIC; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1369,6 +1453,7 @@ TPM_RC + TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_CIPHER_MODE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -1397,6 +1482,7 @@ TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_MODE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -1633,6 +1719,7 @@ TPM_RC + TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); +@@ -1640,6 +1727,7 @@ TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_CREATION) { + rc = TPM_RC_TAG; ++ target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -1657,6 +1745,7 @@ TPM_RC + TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); +@@ -1664,6 +1753,7 @@ TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_VERIFIED) { + rc = TPM_RC_TAG; ++ target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -1681,6 +1771,7 @@ TPM_RC + TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); +@@ -1689,6 +1780,7 @@ TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size) + if ((target->tag != TPM_ST_AUTH_SIGNED) && + (target->tag != TPM_ST_AUTH_SECRET)) { + rc = TPM_RC_TAG; ++ target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -1706,6 +1798,7 @@ TPM_RC + TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPM_ST orig_tag = target->tag; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(&target->tag, buffer, size); +@@ -1713,6 +1806,7 @@ TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *siz + if (rc == TPM_RC_SUCCESS) { + if (target->tag != TPM_ST_HASHCHECK) { + rc = TPM_RC_TAG; ++ target->tag = orig_tag; // libtpms added + } + } + if (rc == TPM_RC_SUCCESS) { +@@ -2303,6 +2397,7 @@ TPM_RC + TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ST_ATTEST orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ST_Unmarshal(target, buffer, size); +@@ -2319,6 +2414,7 @@ TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_SELECTOR; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -2413,6 +2509,7 @@ TPM_RC + TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_AES_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); +@@ -2424,6 +2521,7 @@ TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *siz + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -2435,6 +2533,7 @@ TPM_RC + TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_CAMELLIA_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); +@@ -2445,6 +2544,7 @@ TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -2456,6 +2556,7 @@ TPM_RC + TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); +@@ -2466,6 +2567,7 @@ TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *siz + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -2477,6 +2579,7 @@ TPM_RC + TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); +@@ -2488,6 +2591,7 @@ TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *si + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -2760,6 +2864,7 @@ TPM_RC + TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_KEYEDHASH_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -2779,6 +2884,7 @@ TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **bu + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3163,6 +3269,7 @@ TPM_RC + TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_ASYM_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -3206,6 +3313,7 @@ TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT3 + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3284,6 +3392,7 @@ TPM_RC + TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_RSA_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -3309,6 +3418,7 @@ TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3336,6 +3446,7 @@ TPM_RC + TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_RSA_DECRYPT orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -3355,6 +3466,7 @@ TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT3 + } + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3395,6 +3507,7 @@ TPM_RC + TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_RSA_KEY_BITS orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); +@@ -3406,6 +3519,7 @@ TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *siz + break; + default: + rc = TPM_RC_VALUE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3490,6 +3604,7 @@ TPM_RC + TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_ECC_SCHEME orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -3521,6 +3636,7 @@ TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 + } + default: + rc = TPM_RC_SCHEME; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3532,6 +3648,7 @@ TPM_RC + TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ECC_CURVE orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ECC_CURVE_Unmarshal(target, buffer, size); +@@ -3568,6 +3685,7 @@ TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_CURVE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -3782,6 +3900,7 @@ TPM_RC + TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMI_ALG_PUBLIC orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = TPM_ALG_ID_Unmarshal(target, buffer, size); +@@ -3803,6 +3922,7 @@ TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size) + break; + default: + rc = TPM_RC_TYPE; ++ *target = orig_target; // libtpms added + } + } + return rc; +@@ -4137,6 +4257,7 @@ TPM_RC + TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size) + { + TPM_RC rc = TPM_RC_SUCCESS; ++ TPMA_NV orig_target = *target; // libtpms added + + if (rc == TPM_RC_SUCCESS) { + rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ +@@ -4144,6 +4265,7 @@ TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size) + if (rc == TPM_RC_SUCCESS) { + if (*target & TPMA_NV_RESERVED) { + rc = TPM_RC_RESERVED_BITS; ++ *target = orig_target; // libtpms added + } + } + return rc; +-- +2.27.0 + diff --git a/tpm2-add-SM3-and-SM4-support.patch b/tpm2-add-SM3-and-SM4-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..e7d9a1197f3c96e29f018f57b140a06c1efdf621 --- /dev/null +++ b/tpm2-add-SM3-and-SM4-support.patch @@ -0,0 +1,849 @@ +From 16363870ff82bf427355ccd6517538e1c121427b Mon Sep 17 00:00:00 2001 +From: fly2x +Date: Thu, 14 Dec 2023 19:55:14 +0800 +Subject: [PATCH] tpm2 add SM3 and SM4 support + +--- + configure.ac | 10 ++ + src/tpm2/AlgorithmTests.c | 7 +- + src/tpm2/HashTestData.h | 9 ++ + src/tpm2/Marshal.c | 9 ++ + src/tpm2/Marshal_fp.h | 4 + + src/tpm2/NVMarshal.c | 141 ++++++++++++++++++++++++ + src/tpm2/SymmetricTest.h | 4 +- + src/tpm2/SymmetricTestData.h | 45 ++++++++ + src/tpm2/Unmarshal_fp.h | 4 + + src/tpm2/crypto/CryptHash.h | 3 + + src/tpm2/crypto/CryptSym.h | 5 + + src/tpm2/crypto/openssl/CryptCmac.c | 10 ++ + src/tpm2/crypto/openssl/CryptHash.c | 8 ++ + src/tpm2/crypto/openssl/CryptSym.c | 18 +++ + src/tpm2/crypto/openssl/Helpers.c | 127 ++++++++++++++++++++- + src/tpm2/crypto/openssl/TpmToOsslHash.h | 41 ++++++- + src/tpm2/crypto/openssl/TpmToOsslSym.h | 37 ++++++- + 17 files changed, 471 insertions(+), 11 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 0c57ef3..e85c5fa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -237,6 +237,15 @@ AC_ARG_ENABLE([test-coverage], + AS_HELP_STRING([--enable-test-coverage], [Enable test coverage flags]), + [COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage" COVERAGE_LDFLAGS="-fprofile-arcs"]) + ++AC_ARG_WITH([openssl-SM], ++ AS_HELP_STRING([--with-openssl-SM], [libtpms supports SM3 and SM4, default not support]), [with_openssl_SM=yes], [with_openssl_SM=no] ++) ++ ++AS_IF([test "x$with_openssl_SM" != "xno"], [ ++ AC_DEFINE([ALG_SM3_256], [1], [1 denotes to support SM3, and 0 not support]) ++ AC_DEFINE([ALG_SM4], [1], [1 denotes to support SM4, and 0 not support]) ++]) ++ + LT_INIT + AC_PROG_CC + AC_PROG_CXX +@@ -316,6 +325,7 @@ echo "Version to build : $PACKAGE_VERSION" + echo "Crypto library : $cryptolib" + echo "Debug build : $enable_debug" + echo "With TPM2 support : $with_tpm2" ++echo "With SM3 and SM4 support: $with_openssl_SM" + echo "HAVE_VERSION_SCRIPT : $have_version_script" + echo "Use openssl crypto for : $use_openssl_functions_for" + echo +diff --git a/src/tpm2/AlgorithmTests.c b/src/tpm2/AlgorithmTests.c +index d30c6f8..8749ec2 100644 +--- a/src/tpm2/AlgorithmTests.c ++++ b/src/tpm2/AlgorithmTests.c +@@ -860,7 +860,7 @@ TestAlgorithm( + #if ALG_SM4 + // if SM4 is implemented, its test is like other block ciphers but there + // aren't any test vectors for it yet +- // case ALG_SM4_VALUE: ++ case ALG_SM4_VALUE: /* libtpms changed */ + #endif + #if ALG_CAMELLIA + // no test vectors for camellia +@@ -925,10 +925,9 @@ TestAlgorithm( + #if ALG_SHA512 + case ALG_SHA512_VALUE: + #endif // TPM_ALG_SHA512 +- // if SM3 is implemented its test is like any other hash, but there +- // aren't any test vectors yet. ++ + #if ALG_SM3_256 +- // case ALG_SM3_256_VALUE: ++ case ALG_SM3_256_VALUE: /* libtpms changed */ + #endif // TPM_ALG_SM3_256 + if(doTest) + result = TestHash(alg, toTest); +diff --git a/src/tpm2/HashTestData.h b/src/tpm2/HashTestData.h +index d13843a..604fd43 100644 +--- a/src/tpm2/HashTestData.h ++++ b/src/tpm2/HashTestData.h +@@ -127,6 +127,15 @@ TPM2B_SHA512 c_SHA512_digest = {{64, { + }}}; + #endif + ++// libtpms added begin ++#if ALG_SM3_256 == YES ++TPM2B_TYPE(SM3_256, 32); ++TPM2B_SM3_256 c_SM3_256_digest = {{32, { ++ 0xbb,0x9e,0x23,0x79,0xfe,0xbb,0xf8,0xb0,0x1d,0x27,0x5f,0x30,0x71,0xbe,0xce,0x8a, ++ 0xb7,0x3f,0xee,0x6b,0xed,0xd7,0xee,0x45,0x4f,0x80,0xca,0x70,0x6c,0x09,0xb6,0x1a ++ }}}; ++#endif ++// libtpms added end + // libtpms added begin + #if ALG_CMAC + TPM2B_TYPE(AES128, 16); +diff --git a/src/tpm2/Marshal.c b/src/tpm2/Marshal.c +index 39e69e4..aae9a4f 100644 +--- a/src/tpm2/Marshal.c ++++ b/src/tpm2/Marshal.c +@@ -1135,6 +1135,15 @@ TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *siz + return written; + } // libtpms added end + ++#if ALG_SM4 // libtpms added begin ++UINT16 ++TPMI_SM4_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size) ++{ ++ UINT16 written = 0; ++ written += TPM_KEY_BITS_Marshal(source, buffer, size); ++ return written; ++} ++#endif // libtpms added end + /* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union (StructuresTable()) */ + + UINT16 +diff --git a/src/tpm2/Marshal_fp.h b/src/tpm2/Marshal_fp.h +index 582cc9e..f02ff37 100644 +--- a/src/tpm2/Marshal_fp.h ++++ b/src/tpm2/Marshal_fp.h +@@ -228,6 +228,10 @@ extern "C" { + TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size); + UINT16 + TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); ++#if ALG_SM4 ++ UINT16 ++ TPMI_SM4_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); ++#endif + UINT16 + TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); + UINT16 +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 40be17e..d67f5b4 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -1970,6 +1970,135 @@ skip_future_versions: + } + #endif + ++#if ALG_SM3_256 ++ ++#define HASH_STATE_SM3_256_MAGIC 0x10854a09 ++#define HASH_STATE_SM3_256_VERSION 2 ++ ++static UINT16 ++tpmHashStateSM3_256_Marshal(tpmHashStateSM3_256_t *data, BYTE **buffer, INT32 *size, ++ UINT16 hashAlg) ++{ ++ UINT16 written = 0; ++ UINT16 array_size; ++ SM3_CTX *sm3_ctx = NULL; ++ BLOCK_SKIP_INIT; ++ ++ sm3_ctx = EVP_MD_CTX_md_data(*data); ++ written = NV_HEADER_Marshal(buffer, size, ++ HASH_STATE_SM3_256_VERSION, ++ HASH_STATE_SM3_256_MAGIC, 1); ++ written += UINT32_Marshal(&sm3_ctx->A, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->B, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->C, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->D, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->E, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->F, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->G, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->H, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->Nl, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->Nh, buffer, size); ++ /* data must be written as array */ ++ array_size = sizeof(sm3_ctx->data); ++ written += UINT16_Marshal(&array_size, buffer, size); ++ written += Array_Marshal((BYTE *)&sm3_ctx->data[0], array_size, buffer, size); ++ written += UINT32_Marshal(&sm3_ctx->num, buffer, size); ++ written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); ++ /* future versions append below this line */ ++ ++ BLOCK_SKIP_WRITE_POP(size); ++ ++ BLOCK_SKIP_WRITE_CHECK; ++ ++ return written; ++} ++ ++static UINT16 ++tpmHashStateSM3_256_Unmarshal(tpmHashStateSM3_256_t *data, BYTE **buffer, INT32 *size, ++ UINT16 hashAlg) ++{ ++ UINT16 rc = TPM_RC_SUCCESS; ++ UINT16 array_size; ++ NV_HEADER hdr; ++ SM3_CTX *sm3_ctx = NULL; ++ ++ (*data) = EVP_MD_CTX_new(); ++ if ((*data) == NULL) { ++ rc = TPM_RC_FAILURE; ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ EVP_DigestInit_ex(*data, EVP_sm3(), NULL); ++ sm3_ctx = EVP_MD_CTX_md_data(*data); ++ } ++ ++ if (rc == TPM_RC_SUCCESS) { ++ rc = NV_HEADER_Unmarshal(&hdr, buffer, size, ++ HASH_STATE_SM3_256_VERSION, ++ HASH_STATE_SM3_256_MAGIC); ++ } ++ ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->A, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->B, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->C, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->D, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->E, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->F, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->G, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->H, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->Nl, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->Nh, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT16_Unmarshal(&array_size, buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS && ++ array_size != sizeof(sm3_ctx->data)) { ++ TPMLIB_LogTPM2Error("HASH_STATE_SM3_256: Bad array size for data; " ++ "expected %zu, got %u\n", ++ sizeof(sm3_ctx->data), array_size); ++ rc = TPM_RC_BAD_PARAMETER; ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = Array_Unmarshal((BYTE *)&sm3_ctx->data[0], array_size, ++ buffer, size); ++ } ++ if (rc == TPM_RC_SUCCESS) { ++ rc = UINT32_Unmarshal(&sm3_ctx->num, buffer, size); ++ } ++ ++ /* version 2 starts having indicator for next versions that we can skip; ++ this allows us to downgrade state */ ++ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { ++ BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, ++ "HASH_STATE_SM3_256", "version 3 or later"); ++ /* future versions nest-append here */ ++ } ++skip_future_versions: ++ ++ return rc; ++} ++#endif ++ ++ + #define ANY_HASH_STATE_MAGIC 0x349d494b + #define ANY_HASH_STATE_VERSION 2 + +@@ -2006,6 +2135,12 @@ ANY_HASH_STATE_Marshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + written += tpmHashStateSHA512_Marshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ written += tpmHashStateSM3_256_Marshal(&data->Sm3_256, buffer, size, ++ ALG_SHA512_VALUE); ++ break; + #endif + default: + break; +@@ -2056,6 +2191,12 @@ ANY_HASH_STATE_Unmarshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, + rc = tpmHashStateSHA512_Unmarshal(&data->Sha512, buffer, size, + ALG_SHA512_VALUE); + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ rc = tpmHashStateSM3_256_Unmarshal(&data->Sm3_256, buffer, size, ++ ALG_SHA512_VALUE); ++ break; + #endif + } + +diff --git a/src/tpm2/SymmetricTest.h b/src/tpm2/SymmetricTest.h +index 56580de..72502ce 100644 +--- a/src/tpm2/SymmetricTest.h ++++ b/src/tpm2/SymmetricTest.h +@@ -98,11 +98,11 @@ const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS] = { + # undef COMMA + # define COMMA , + #endif +-#if SM4_128 ++#if ALG_SM4 && SM4_128 + COMMA + {ALG_SM4_VALUE, 128, key_SM4128, 16, sizeof(dataIn_SM4128), dataIn_SM4128, + {dataOut_SM4128_CTR, dataOut_SM4128_OFB, dataOut_SM4128_CBC, +- dataOut_SM4128_CFB, dataOut_AES128_ECB}} ++ dataOut_SM4128_CFB, dataOut_SM4128_ECB}} + #endif + // libtpms added begin + #if TDES_128 +diff --git a/src/tpm2/SymmetricTestData.h b/src/tpm2/SymmetricTestData.h +index f64fb4f..fe850e7 100644 +--- a/src/tpm2/SymmetricTestData.h ++++ b/src/tpm2/SymmetricTestData.h +@@ -269,6 +269,51 @@ const BYTE dataOutShort_TDES192_CFB[] = { + const BYTE dataOutShort_TDES192_OFB[] = { + 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; + #endif ++ ++#if SM4_128 ++// source: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-04#appendix-A.2 ++const BYTE key_SM4128 [] = { ++ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, ++ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; ++const BYTE dataIn_SM4128 [] = { ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, ++ 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, ++ 0xEE, 0xEE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB}; ++const BYTE dataOut_SM4128_ECB [] = { ++ 0x5E, 0xC8, 0x14, 0x3D, 0xE5, 0x09, 0xCF, 0xF7, ++ 0xB5, 0x17, 0x9F, 0x8F, 0x47, 0x4B, 0x86, 0x19, ++ 0x2F, 0x1D, 0x30, 0x5A, 0x7F, 0xB1, 0x7D, 0xF9, ++ 0x85, 0xF8, 0x1C, 0x84, 0x82, 0x19, 0x23, 0x04, ++ 0x00, 0x2A, 0x8A, 0x4E, 0xFA, 0x86, 0x3C, 0xCA, ++ 0xD0, 0x24, 0xAC, 0x03, 0x00, 0xBB, 0x40, 0xD2}; ++const BYTE dataOut_SM4128_CBC [] = { ++ 0x78, 0xEB, 0xB1, 0x1C, 0xC4, 0x0B, 0x0A, 0x48, ++ 0x31, 0x2A, 0xAE, 0xB2, 0x04, 0x02, 0x44, 0xCB, ++ 0x4C, 0xB7, 0x01, 0x69, 0x51, 0x90, 0x92, 0x26, ++ 0x97, 0x9B, 0x0D, 0x15, 0xDC, 0x6A, 0x8F, 0x6D, ++ 0x40, 0xD8, 0x41, 0x32, 0xE9, 0x99, 0x74, 0xA4, ++ 0xA8, 0x80, 0x88, 0x68, 0x42, 0x07, 0x48, 0x59}; ++const BYTE dataOut_SM4128_CFB [] = { ++ 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, ++ 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, ++ 0x69, 0xD4, 0xC5, 0x4E, 0xD4, 0x33, 0xB9, 0xA0, ++ 0x34, 0x60, 0x09, 0xBE, 0xB3, 0x7B, 0x2B, 0x3F}; ++const BYTE dataOut_SM4128_OFB [] = { ++ 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, ++ 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, ++ 0x1D, 0x01, 0xAC, 0xA2, 0x48, 0x7C, 0xA5, 0x82, ++ 0xCB, 0xF5, 0x46, 0x3E, 0x66, 0x98, 0x53, 0x9B}; ++/* The data are obtained by running the commands as below: ++ echo "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFFAAAAAAAABBBBBBBB" | xxd -p -r > plain.txt ++ openssl enc -sm4-ctr -in plain.txt -iv "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" -out out.txt -K "0123456789ABCDEFFEDCBA9876543210" ++*/ ++const BYTE dataOut_SM4128_CTR [] = { ++ 0xF4, 0x88, 0x4C, 0x6D, 0x39, 0x7E, 0x0B, 0x06, ++ 0x3D, 0xAC, 0xD9, 0x46, 0x1A, 0xA4, 0xA5, 0x6A, ++ 0x60, 0xDD, 0xA7, 0x5F, 0x86, 0xBC, 0xFE, 0xA4, ++ 0xF1, 0x5D, 0xB4, 0x6A, 0xD1, 0x4E, 0x7C, 0x7F}; ++#endif + // libtpms added end + + #endif +diff --git a/src/tpm2/Unmarshal_fp.h b/src/tpm2/Unmarshal_fp.h +index 8f148b3..5279671 100644 +--- a/src/tpm2/Unmarshal_fp.h ++++ b/src/tpm2/Unmarshal_fp.h +@@ -286,6 +286,10 @@ extern "C" { + #endif /* libtpms added */ + LIB_EXPORT TPM_RC + TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size); ++#if ALG_SM4 ++ LIB_EXPORT TPM_RC ++ TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size); ++#endif + LIB_EXPORT TPM_RC + TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector); + LIB_EXPORT TPM_RC +diff --git a/src/tpm2/crypto/CryptHash.h b/src/tpm2/crypto/CryptHash.h +index 6ba76c2..ffaa034 100644 +--- a/src/tpm2/crypto/CryptHash.h ++++ b/src/tpm2/crypto/CryptHash.h +@@ -133,6 +133,9 @@ typedef union + #endif + #if ALG_SHA512 + tpmHashStateSHA512_t Sha512; ++#endif ++#if ALG_SM3_256 ++ tpmHashStateSM3_256_t Sm3_256; + #endif + // Additions for symmetric block cipher MAC + #if SMAC_IMPLEMENTED +diff --git a/src/tpm2/crypto/CryptSym.h b/src/tpm2/crypto/CryptSym.h +index 7c84279..d481b33 100644 +--- a/src/tpm2/crypto/CryptSym.h ++++ b/src/tpm2/crypto/CryptSym.h +@@ -94,6 +94,9 @@ union tpmCryptKeySchedule_t { + encrypt(SWIZZLE(keySchedule, in, out)) + # define DECRYPT(keySchedule, in, out) \ + decrypt(SWIZZLE(keySchedule, in, out)) ++ ++# define FINAL(keySchedule) final((void *)(keySchedule)) // libtpms added ++ + /* Note that the macros rely on encrypt as local values in the functions that use these + macros. Those parameters are set by the macro that set the key schedule to be used for the + call. */ +@@ -101,11 +104,13 @@ union tpmCryptKeySchedule_t { + case TPM_ALG_##ALG: \ + TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \ + encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \ ++ final = (TpmCryptSymFinal_t)TpmCryptFinal##ALG; /* libtpms added */ \ + break; + #define DECRYPT_CASE(ALG) \ + case TPM_ALG_##ALG: \ + TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.ALG); \ + decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \ ++ final = (TpmCryptSymFinal_t)TpmCryptFinal##ALG; /* libtpms added */ \ + break; + #if ALG_AES + #define ENCRYPT_CASE_AES ENCRYPT_CASE(AES) +diff --git a/src/tpm2/crypto/openssl/CryptCmac.c b/src/tpm2/crypto/openssl/CryptCmac.c +index 8e35a59..2b28723 100644 +--- a/src/tpm2/crypto/openssl/CryptCmac.c ++++ b/src/tpm2/crypto/openssl/CryptCmac.c +@@ -120,6 +120,7 @@ CryptCmacData( + UINT16 keySizeInBits = cmacState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + // + SELECT(ENCRYPT); + while(size > 0) +@@ -135,6 +136,10 @@ CryptCmacData( + cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; + } + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + } + /* 10.2.6.3.3 CryptCmacEnd() */ + /* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey +@@ -154,6 +159,7 @@ CryptCmacEnd( + UINT16 keySizeInBits = cState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + TPM2B_IV subkey = {{0, {0}}}; + BOOL xorVal; + UINT16 i; +@@ -186,6 +192,10 @@ CryptCmacEnd( + ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); + i = (UINT16)MIN(cState->iv.t.size, outSize); + MemoryCopy(outBuffer, cState->iv.t.buffer, i); ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return i; + } + #endif +diff --git a/src/tpm2/crypto/openssl/CryptHash.c b/src/tpm2/crypto/openssl/CryptHash.c +index fdf66b5..3cdb5a8 100644 +--- a/src/tpm2/crypto/openssl/CryptHash.c ++++ b/src/tpm2/crypto/openssl/CryptHash.c +@@ -79,6 +79,9 @@ HASH_DEF_TEMPLATE(SHA384); + #if ALG_SHA512 + HASH_DEF_TEMPLATE(SHA512); + #endif ++#if ALG_SM3_256 ++HASH_DEF_TEMPLATE(SM3_256); ++#endif + HASH_DEF nullDef = {{0}}; + /* 10.2.13.3 Obligatory Initialization Functions */ + /* This function is called by _TPM_Init() do perform the initialization operations for the +@@ -134,6 +137,11 @@ CryptGetHashDef( + case ALG_SHA512_VALUE: + retVal = &SHA512_Def; + break; ++#endif ++#if ALG_SM3_256 ++ case ALG_SM3_256_VALUE: ++ retVal = &SM3_256_Def; ++ break; + #endif + default: + retVal = &nullDef; +diff --git a/src/tpm2/crypto/openssl/CryptSym.c b/src/tpm2/crypto/openssl/CryptSym.c +index 856def6..9c1f501 100644 +--- a/src/tpm2/crypto/openssl/CryptSym.c ++++ b/src/tpm2/crypto/openssl/CryptSym.c +@@ -184,6 +184,7 @@ CryptSymmetricEncrypt( + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + TpmCryptSetSymKeyCall_t encrypt; ++ TpmCryptSymFinal_t final; + BYTE *iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // +@@ -296,8 +297,16 @@ CryptSymmetricEncrypt( + break; + #endif + default: ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_FAILURE; + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_SUCCESS; + } + /* 10.2.20.5.1 CryptSymmetricDecrypt() */ +@@ -328,6 +337,7 @@ CryptSymmetricDecrypt( + BYTE *iv; + TpmCryptSetSymKeyCall_t encrypt; + TpmCryptSetSymKeyCall_t decrypt; ++ TpmCryptSymFinal_t final; /* libtpms added */ + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // These are used but the compiler can't tell because they are initialized + // in case statements and it can't tell if they are always initialized +@@ -457,8 +467,16 @@ CryptSymmetricDecrypt( + break; + #endif + default: ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_FAILURE; + } ++ /* libtpms added begin */ ++ if (final) ++ FINAL(&keySchedule); ++ /* libtpms added end */ + return TPM_RC_SUCCESS; + } + +diff --git a/src/tpm2/crypto/openssl/Helpers.c b/src/tpm2/crypto/openssl/Helpers.c +index 8a33259..0d34582 100644 +--- a/src/tpm2/crypto/openssl/Helpers.c ++++ b/src/tpm2/crypto/openssl/Helpers.c +@@ -187,8 +187,35 @@ evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN + } + #endif + #if ALG_SM4 +-#error Missing implementation of EVP for SM4 + case TPM_ALG_SM4: ++ *keyToUseLen = keySizeInBytes; ++ switch (mode) { ++#if ALG_CTR ++ case TPM_ALG_CTR: ++ evpfn = (evpfunc[]){EVP_sm4_ctr, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_OFB ++ case TPM_ALG_OFB: ++ evpfn = (evpfunc[]){EVP_sm4_ofb, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_CBC ++ case TPM_ALG_CBC: ++ evpfn = (evpfunc[]){EVP_sm4_cbc, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_CFB ++ case TPM_ALG_CFB: ++ evpfn = (evpfunc[]){EVP_sm4_cfb, NULL, NULL}[i]; ++ break; ++#endif ++#if ALG_ECB ++ case TPM_ALG_ECB: ++ evpfn = (evpfunc[]){EVP_sm4_ecb, NULL, NULL}[i]; ++ break; ++#endif ++ } + break; + #endif + #if ALG_CAMELLIA +@@ -264,11 +291,16 @@ static const struct hnames { + .name = "sha512", + .hashAlg = ALG_SHA512_VALUE, + }, { ++#endif ++#if ALG_SM3_256 ++ .name = "sm3", ++ .hashAlg = ALG_SM3_256_VALUE, ++ }, { + #endif + .name = NULL, + } + }; +-#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 ++#if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 + ALG_SM3_256 + # error Missing entry in hnames array! + #endif + +@@ -493,3 +525,94 @@ OpenSSLCryptRsaGenerateKey( + } + + #endif // USE_OPENSSL_FUNCTIONS_RSA ++ ++#if ALG_SM4 ++static int SetSM4Key(const uint8_t *key, SM4_KEY *ks, int direction) ++{ ++ int rc = 0; ++ UINT8 iv[MAX_SM4_BLOCK_SIZE_BYTES] = { 0 }; ++ const EVP_CIPHER *sm4Cipher = EVP_sm4_ecb(); ++ ++ *ks = EVP_CIPHER_CTX_new(); ++ if (*ks == NULL) { ++ return SM4_FAIL; ++ } ++ if (direction == SM4_ENCRYPT) { ++ rc = EVP_EncryptInit_ex(*ks, sm4Cipher, NULL, key, iv); ++ } else { ++ rc = EVP_DecryptInit_ex(*ks, sm4Cipher, NULL, key, iv); ++ } ++ if (rc != SM4_SUCCESS) { ++ return SM4_FAIL; ++ } ++ return SM4_SUCCESS; ++} ++ ++int SM4_set_encrypt_key(const uint8_t *key, SM4_KEY *ks) ++{ ++ return SetSM4Key(key, ks, SM4_ENCRYPT); ++} ++ ++int SM4_set_decrypt_key(const uint8_t *key, SM4_KEY *ks) ++{ ++ return SetSM4Key(key, ks, SM4_DECRYPT); ++} ++ ++static void SM4EncryptDecrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks, int direction) ++{ ++ int outLen = SM4_128_BLOCK_SIZE_BYTES; ++ int rc = 0; ++ ++ if (direction == SM4_ENCRYPT) { ++ rc = EVP_EncryptUpdate(*ks, out, &outLen, in, SM4_128_BLOCK_SIZE_BYTES); ++ } else { ++ rc = EVP_DecryptUpdate(*ks, out, &outLen, in, SM4_128_BLOCK_SIZE_BYTES); ++ } ++ pAssert(rc != SM4_SUCCESS || outLen != SM4_128_BLOCK_SIZE_BYTES); ++} ++ ++void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) ++{ ++ SM4EncryptDecrypt(in, out, ks, SM4_ENCRYPT); ++} ++ ++void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks) ++{ ++ SM4EncryptDecrypt(in, out, ks, SM4_DECRYPT); ++} ++ ++void SM4_final(const SM4_KEY *ks) ++{ ++ if (*ks != NULL) { ++ EVP_CIPHER_CTX_cleanup(*ks); ++ } ++} ++#endif ++#if ALG_SM3_256 ++int sm3_init(SM3_TPM_CTX *c) ++{ ++ *c = EVP_MD_CTX_new(); ++ if (*c == NULL) { ++ return SM3_FAIL; ++ } ++ return EVP_DigestInit_ex(*c, EVP_sm3(), NULL); ++} ++ ++int sm3_update(SM3_TPM_CTX *c, const void *data, size_t len) ++{ ++ return EVP_DigestUpdate(*c, data, len); ++} ++ ++int sm3_final(unsigned char *md, SM3_TPM_CTX *c) ++{ ++ uint32_t len = SM3_256_DIGEST_SIZE; ++ int ret = EVP_DigestFinal_ex(*c, md, &len); ++ ++ if (ret != SM3_SUCCESS || len != SM3_256_DIGEST_SIZE) { ++ ret = SM3_FAIL; ++ } ++ EVP_MD_CTX_destroy(*c); ++ *c = NULL; ++ return ret; ++} ++#endif +diff --git a/src/tpm2/crypto/openssl/TpmToOsslHash.h b/src/tpm2/crypto/openssl/TpmToOsslHash.h +index 7624824..78a1d93 100644 +--- a/src/tpm2/crypto/openssl/TpmToOsslHash.h ++++ b/src/tpm2/crypto/openssl/TpmToOsslHash.h +@@ -71,6 +71,35 @@ + #include + #include + #include ++ ++#if ALG_SM3_256 ++# if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L ++# if ALG_SM3_256 // libtpms added begin ++# error This version of OpenSSL does not support SM3 ++# endif // libtpms added end ++# undef ALG_SM3_256 ++# define ALG_SM3_256 ALG_NO ++# else ++# include ++ ++# define SM3_LBLOCK (64/4) ++# define SM3_SUCCESS 1 ++# define SM3_FAIL 0 ++typedef struct SM3state_st { ++ unsigned int A, B, C, D, E, F, G, H; ++ unsigned int Nl, Nh; ++ unsigned int data[SM3_LBLOCK]; ++ unsigned int num; ++} SM3_CTX; ++ ++typedef EVP_MD_CTX* SM3_TPM_CTX; ++ ++int sm3_init(SM3_TPM_CTX *c); ++int sm3_update(SM3_TPM_CTX *c, const void *data, size_t len); ++int sm3_final(unsigned char *md, SM3_TPM_CTX *c); ++#endif ++#endif // ALG_SM3_256 ++ + /* B.2.2.1.2. Links to the OpenSSL HASH code */ + /* Redefine the internal name used for each of the hash state structures to the name used by the + library. These defines need to be known in all parts of the TPM so that the structure sizes can +@@ -80,8 +109,9 @@ + #define tpmHashStateSHA384_t SHA512_CTX + #define tpmHashStateSHA512_t SHA512_CTX + #if ALG_SM3_256 +-# error "The version of OpenSSL used by this code does not support SM3" ++#define tpmHashStateSM3_256_t SM3_TPM_CTX + #endif ++ + /* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation + is primarily to avoid name space collision. However, if there is a real collision, it will + likely show up when the linker tries to put things together. */ +@@ -171,6 +201,15 @@ typedef const BYTE *PCBYTE; + #define tpmHashStateCopy_SHA512 memcpy + #define tpmHashStateExport_SHA512 memcpy + #define tpmHashStateImport_SHA512 memcpy ++#if ALG_SM3_256 ++#define tpmHashStart_SM3_256 sm3_init ++#define tpmHashData_SM3_256 sm3_update ++#define tpmHashEnd_SM3_256 sm3_final ++#define tpmHashStateCopy_SM3_256 memcpy ++#define tpmHashStateExport_SM3_256 memcpy ++#define tpmHashStateImport_SM3_256 memcpy ++#endif ++ + #endif // _CRYPT_HASH_C_ + #define LibHashInit() + /* This definition would change if there were something to report */ +diff --git a/src/tpm2/crypto/openssl/TpmToOsslSym.h b/src/tpm2/crypto/openssl/TpmToOsslSym.h +index 646d16d..1eee9c9 100644 +--- a/src/tpm2/crypto/openssl/TpmToOsslSym.h ++++ b/src/tpm2/crypto/openssl/TpmToOsslSym.h +@@ -76,8 +76,25 @@ + #include + /* B.2.2.3.2. Links to the OpenSSL AES code */ + #if ALG_SM4 +-#error "SM4 is not available" +-#endif ++# if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L ++# undef ALG_SM4 ++# define ALG_SM4 ALG_NO ++# else ++# include ++ typedef EVP_CIPHER_CTX* SM4_KEY; ++# define SM4_ENCRYPT 1 ++# define SM4_DECRYPT 0 ++# define SM4_SUCCESS 1 ++# define SM4_FAIL 0 ++ ++int SM4_set_encrypt_key(const uint8_t *key, SM4_KEY *ks); ++int SM4_set_decrypt_key(const uint8_t *key, SM4_KEY *ks); ++void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); ++void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); ++void SM4_final(const SM4_KEY *ks); ++# endif ++#endif // ALG_SM4 ++ + #if ALG_CAMELLIA + #error "Camellia is not available" + #endif +@@ -88,6 +105,7 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + BYTE *out, + void *keySchedule + ); ++typedef void(*TpmCryptSymFinal_t)(void *keySchedule); /* libtpms added */ + /* The Crypt functions that call the block encryption function use the parameters in the order: */ + /* a) keySchedule */ + /* b) in buffer */ +@@ -106,6 +124,11 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) + #define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) ++#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \ ++ SM4_set_encrypt_key((key), (tpmKeyScheduleSM4 *)(schedule)) /* libtpms changed */ ++#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \ ++ SM4_set_decrypt_key((key), (tpmKeyScheduleSM4 *)(schedule)) /* libtpms changed */ ++ + /* Macros to alias encryption calls to specific algorithms. This should be used + sparingly. Currently, only used by CryptRand.c */ + /* When using these calls, to call the AES block encryption code, the caller should use: +@@ -113,9 +136,19 @@ typedef void(*TpmCryptSetSymKeyCall_t)( + #define TpmCryptEncryptAES AES_encrypt + #define TpmCryptDecryptAES AES_decrypt + #define tpmKeyScheduleAES AES_KEY ++#define TpmCryptFinalAES NULL /* libtpms added */ ++ + #define TpmCryptEncryptTDES TDES_encrypt + #define TpmCryptDecryptTDES TDES_decrypt + #define tpmKeyScheduleTDES DES_key_schedule ++#define TpmCryptFinalTDES NULL /* libtpms added */ ++ ++#define TpmCryptEncryptSM4 SM4_encrypt /* libtpms added */ ++#define TpmCryptDecryptSM4 SM4_decrypt /* libtpms added */ ++#define tpmKeyScheduleSM4 SM4_KEY /* libtpms added */ ++#define TpmCryptFinalSM4 SM4_final /* libtpms added */ ++ ++ + typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + #if ALG_TDES + #include "TpmToOsslDesSupport_fp.h" +-- +2.39.3 (Apple Git-145) + diff --git a/tpm2-rev155-Add-new-RsaAdjustPrimeCandidate-code.patch b/tpm2-rev155-Add-new-RsaAdjustPrimeCandidate-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..60957e0700ad67138df8d3e39e80f7019ec6fc70 --- /dev/null +++ b/tpm2-rev155-Add-new-RsaAdjustPrimeCandidate-code.patch @@ -0,0 +1,172 @@ +From b4ff6345a6b1533f907ed1922d884acae62d2501 Mon Sep 17 00:00:00 2001 +From: jiangfangjie 00559066 +Date: Tue, 11 May 2021 11:52:44 +0800 +Subject: [PATCH 4/7] tpm2: rev155: Add new RsaAdjustPrimeCandidate code but + do not use + +Add in the new RsaAdjustPrimeCandidate() function but do not use it +so far since it creates slightly different primes than the previous +code and we would get different derived keys if we were to use it with +'old' seeds. + +Adjust the code to return the same results for 64 bit and 32 bit machines. +--- + src/tpm2/crypto/openssl/CryptPrime.c | 110 ++++++++++++++++++++++----- + 1 file changed, 89 insertions(+), 21 deletions(-) + +diff --git a/src/tpm2/crypto/openssl/CryptPrime.c b/src/tpm2/crypto/openssl/CryptPrime.c +index 662c762..9a5ee7d 100644 +--- a/src/tpm2/crypto/openssl/CryptPrime.c ++++ b/src/tpm2/crypto/openssl/CryptPrime.c +@@ -3,7 +3,7 @@ + /* Code for prime validation. */ + /* Written by Ken Goldman */ + /* IBM Thomas J. Watson Research Center */ +-/* $Id: CryptPrime.c 1262 2018-07-11 21:03:43Z kgoldman $ */ ++/* $Id: CryptPrime.c 1476 2019-06-10 19:32:03Z kgoldman $ */ + /* */ + /* Licenses and Notices */ + /* */ +@@ -55,7 +55,7 @@ + /* arising in any way out of use or reliance upon this specification or any */ + /* information herein. */ + /* */ +-/* (c) Copyright IBM Corp. and others, 2016 - 2018 */ ++/* (c) Copyright IBM Corp. and others, 2016 - 2019 */ + /* */ + /********************************************************************************/ + +@@ -292,19 +292,14 @@ RsaCheckPrime( + return PrimeSelectWithSieve(prime, exponent, rand); + #endif + } +-/* 10.2.16.1.7 AdjustPrimeCandiate() */ +-/* This function adjusts the candidate prime so that it is odd and > root(2)/2. This allows the +- product of these two numbers to be .5, which, in fixed point notation means that the most +- significant bit is 1. For this routine, the root(2)/2 is approximated with 0xB505 which is, in +- fixed point is 0.7071075439453125 or an error of 0.0001%. Just setting the upper two bits would +- give a value > 0.75 which is an error of > 6%. Given the amount of time all the other +- computations take, reducing the error is not much of a cost, but it isn't totally required +- either. */ +-/* The function also puts the number on a field boundary. */ +-LIB_EXPORT void +-RsaAdjustPrimeCandidate( +- bigNum prime +- ) ++/* ++ * RsaAdjustPrimeCandidate_PreRev155 is the pre-rev.155 algorithm used; we ++ * still have to use it for old seeds to maintain backwards compatibility. ++ */ ++static void ++RsaAdjustPrimeCandidate_PreRev155( ++ bigNum prime ++ ) + { + UINT16 highBytes; + crypt_uword_t *msw = &prime->d[prime->size - 1]; +@@ -316,14 +311,74 @@ RsaAdjustPrimeCandidate( + *msw = ((crypt_uword_t)(highBytes) << (RADIX_BITS - 16)) + (*msw & MASK); + prime->d[0] |= 1; + } +-/* 10.2.16.1.8 BnGeneratePrimeForRSA() */ ++ ++/* 10.2.14.1.7 RsaAdjustPrimeCandidate() */ ++ ++/* For this math, we assume that the RSA numbers are fixed-point numbers with the decimal point to ++ the left of the most significant bit. This approach helps make it clear what is happening with ++ the MSb of the values. The two RSA primes have to be large enough so that their product will be a ++ number with the necessary number of significant bits. For example, we want to be able to multiply ++ two 1024-bit numbers to produce a number with 2028 significant bits. If we accept any 1024-bit ++ prime that has its MSb set, then it is possible to produce a product that does not have the MSb ++ SET. For example, if we use tiny keys of 16 bits and have two 8-bit primes of 0x80, then the ++ public key would be 0x4000 which is only 15-bits. So, what we need to do is made sure that each ++ of the primes is large enough so that the product of the primes is twice as large as each ++ prime. A little arithmetic will show that the only way to do this is to make sure that each of ++ the primes is no less than root(2)/2. That's what this functions does. This function adjusts the ++ candidate prime so that it is odd and >= root(2)/2. This allows the product of these two numbers ++ to be .5, which, in fixed point notation means that the most significant bit is 1. For this ++ routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 which is, in fixed point, ++ 0.7071075439453125 or an error of 0.000108%. Just setting the upper two bits would give a value > ++ 0.75 which is an error of > 6%. Given the amount of time all the other computations take, ++ reducing the error is not much of a cost, but it isn't totally required either. */ ++/* This function can be replaced with a function that just sets the two most significant bits of ++ each prime candidate without introducing any computational issues. */ ++ ++static void ++RsaAdjustPrimeCandidate_New( ++ bigNum prime ++ ) ++{ ++ UINT32 msw; ++ UINT32 adjusted; ++ ++ // If the radix is 32, the compiler should turn this into a simple assignment ++ msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0); ++ // Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0 ++ adjusted = (msw >> 16) * 0x4AFB; ++ adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16; ++ adjusted += 0xB5050000UL; ++#if RADIX_BITS == 64 ++ // Save the low-order 32 bits ++ prime->d[prime->size - 1] &= 0xFFFFFFFFUL; ++ // replace the upper 32-bits ++ prime->d[prime->size -1] |= ((crypt_uword_t)adjusted << 32); ++#else ++ prime->d[prime->size - 1] = (crypt_uword_t)adjusted; ++#endif ++ // make sure the number is odd ++ prime->d[0] |= 1; ++} ++LIB_EXPORT void ++RsaAdjustPrimeCandidate( ++ bigNum prime ++ ) ++{ ++ if (1) ++ RsaAdjustPrimeCandidate_PreRev155(prime); ++ else ++ RsaAdjustPrimeCandidate_New(prime); ++} ++/* 10.2.14.1.8 BnGeneratePrimeForRSA() */ ++ + /* Function to generate a prime of the desired size with the proper attributes for an RSA prime. */ + void + BnGeneratePrimeForRSA( +- bigNum prime, +- UINT32 bits, +- UINT32 exponent, +- RAND_STATE *rand ++ bigNum prime, // IN/OUT: points to the BN that will get the ++ // random value ++ UINT32 bits, // IN: number of bits to get ++ UINT32 exponent, // IN: the exponent ++ RAND_STATE *rand // IN: the random state + ) + { + BOOL found = FALSE; +@@ -335,8 +390,21 @@ BnGeneratePrimeForRSA( + prime->size = BITS_TO_CRYPT_WORDS(bits); + while(!found) + { +- DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits)); ++ // The change below is to make sure that all keys that are generated from the same ++ // seed value will be the same regardless of the endianess or word size of the CPU. ++ // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old ++ // if(g_inFailureMode) // old ++ // libtpms changed begin ++ if (1) { ++ DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits)); ++ if (g_inFailureMode) ++ return; ++ } else { ++ if(!BnGetRandomBits(prime, bits, rand)) // new ++ return; ++ } + RsaAdjustPrimeCandidate(prime); ++ // libtpms changed end + found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS; + } + } +-- +2.21.0.windows.1 +