diff --git a/libtpms.spec b/libtpms.spec index b6b41cb4fcb9269dcc1076621795fa40a6629b71..d5949da6820cf96dc998abe15c89110a1ccb422e 100644 --- a/libtpms.spec +++ b/libtpms.spec @@ -6,7 +6,7 @@ %define name libtpms %define versionx 0.7.3 -%define release 3 +%define release 4 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" @@ -19,7 +19,7 @@ Summary: Library providing Trusted Platform Module (TPM) functionality Name: %{name} Version: %{versionx} -Release: 3 +Release: 4 License: BSD Group: Development/Libraries Url: http://github.com/stefanberger/libtpms @@ -27,6 +27,13 @@ Source0: %{url}/archive/%{gitcommit}/%{name}-%{gitshortcommit}.tar.gz Provides: libtpms-%{crypto_subsystem} = %{version}-%{release} Patch0: 0001-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 %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel @@ -119,6 +126,12 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %postun -p /sbin/ldconfig %changelog +* 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 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-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-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-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 +