!13 FIX the issue where the lenth of the generated prime value is insufficient

From: @jackjf
Reviewed-by: @zhujianwei001
Signed-off-by: @zhujianwei001
This commit is contained in:
openeuler-ci-bot 2021-09-09 09:30:36 +00:00 committed by Gitee
commit 15b16e6b47
8 changed files with 948 additions and 2 deletions

View File

@ -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 <jiangfangjie@huawei.com> - 0.7.3-4
-TYPE: CVE
-ID:NA
-SUG:NA
-DESC:fix CVE-2021-3505
* Mon Apr 5 2021 jiangfangjie <jiangfangjie@huawei.com> - 0.7.3-3
- Type:CVE
- ID:NA

View File

@ -0,0 +1,52 @@
From eb36e429ebe6d0dd7e1ca07013245ab766eec02d Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,143 @@
From 8b534099d59ec5e746802dd77680612539945324 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,110 @@
From 6617eecb7ea815974a1cfc19f60a091f64c7ba30 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,346 @@
From 2833825447cbc0b23c1aa13a15521aa1d0ec0175 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,25 @@
From 087e54dcc99a36151677581eda92c321907988d9 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,85 @@
From 5ffbddedaedc3215da219d35dc3f95b1c52ef393 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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

View File

@ -0,0 +1,172 @@
From b4ff6345a6b1533f907ed1922d884acae62d2501 Mon Sep 17 00:00:00 2001
From: jiangfangjie 00559066 <jiangfangjie@huawei.com>
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