347 lines
14 KiB
Diff
347 lines
14 KiB
Diff
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
|
|
|