File extra-self-tests.patch of Package pcr-oracle
From 1601cfe8d1dd9e8ed30efa7a234e668ee96ab855 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Tue, 23 Sep 2025 14:46:40 +0800
Subject: [PATCH 1/3] Extra checks for TPM self-test
Do a few more checks besides the TPM SelfTest command
- Check the TPM properties: PropertyStartupClear and PropertyPermanent
- Check the tagged policies associated with the following permanent
handles: TPM2_RH_LOCKOUT, TPM2_RH_OWNER, and TPM2_RH_ENDORSEMENT
Signed-off-by: Gary Lin <glin@suse.com>
---
src/tpm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 191 insertions(+), 1 deletion(-)
diff --git a/src/tpm.c b/src/tpm.c
index 84b5dbe..fdfffc8 100644
--- a/src/tpm.c
+++ b/src/tpm.c
@@ -85,14 +85,204 @@ tss_esys_context(void)
return esys_ctx;
}
+static bool
+tpm_get_tpm_property(TPM2_PT property, uint32_t *value)
+{
+ ESYS_CONTEXT *esys_ctx = tss_esys_context();
+ TPMS_CAPABILITY_DATA *cap_data = NULL;
+ TPMI_YES_NO more_data;
+ TPML_TAGGED_TPM_PROPERTY *props = NULL;
+ TSS2_RC rc;
+ bool okay = false;
+
+ if (value == NULL)
+ return false;
+
+ rc = Esys_GetCapability(esys_ctx, ESYS_TR_NONE, ESYS_TR_NONE,
+ ESYS_TR_NONE, TPM2_CAP_TPM_PROPERTIES, property,
+ 1, &more_data, &cap_data);
+ if (rc != TSS2_RC_SUCCESS)
+ return tss_check_error(rc, "Esys_GetCapability (TPM_PROPERTIES) failed");
+
+ if (cap_data == NULL) {
+ error("Empty CAP data (TPM_PROPERTIES)\n");
+ return false;
+ }
+
+ if (cap_data->capability != TPM2_CAP_TPM_PROPERTIES) {
+ error("Wrong CAP data (TPM_PROPERTIES)\n");
+ goto out;
+ }
+
+ props = &cap_data->data.tpmProperties;
+ if (props->count != 1) {
+ error("Got more than 1 property\n");
+ goto out;
+ }
+
+ if (props->tpmProperty[0].property != property) {
+ error("Property not match\n");
+ goto out;
+ }
+
+ *value = props->tpmProperty[0].value;
+
+ okay = true;
+out:
+ if (cap_data)
+ free(cap_data);
+
+ return okay;
+}
+
+#ifdef TPM2_CAP_AUTH_POLICIES
+static bool
+tpm_get_auth_policies(TPM2_HANDLE hierarchy, TPMS_CAPABILITY_DATA **cap_data)
+{
+ ESYS_CONTEXT *esys_ctx = tss_esys_context();
+ TPMI_YES_NO more_data;
+ TSS2_RC rc;
+
+ rc = Esys_GetCapability(esys_ctx, ESYS_TR_NONE, ESYS_TR_NONE,
+ ESYS_TR_NONE, TPM2_CAP_AUTH_POLICIES, hierarchy,
+ TPM2_MAX_TAGGED_POLICIES, &more_data, cap_data);
+ if (rc != TSS2_RC_SUCCESS)
+ return tss_check_error(rc, "Esys_GetCapability (AUTH_POLICIES) failed");
+
+ if (*cap_data == NULL) {
+ error("Empty CAP data (AUTH_POLICIES)\n");
+ return false;
+ }
+
+ if ((*cap_data)->capability != TPM2_CAP_AUTH_POLICIES) {
+ error("Wrong CAP data (AUTH_POLICIES)\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+tpm_check_auth_policies(TPM2_HANDLE hierarchy)
+{
+ TPMS_CAPABILITY_DATA *cap_data = NULL;
+ TPML_TAGGED_POLICY *policies = NULL;
+ uint32_t i;
+ bool okay = false;
+
+ if (!tpm_get_auth_policies(hierarchy, &cap_data))
+ goto out;
+
+ policies = &cap_data->data.authPolicies;
+ for (i = 0; i < policies->count; i++) {
+ if (policies->policies[i].policyHash.hashAlg != TPM2_ALG_NULL) {
+ error("Tagged policy NON-NULL Hash Algorithm\n");
+ goto out;
+ }
+ }
+
+ okay = true;
+out:
+ if (cap_data)
+ free(cap_data);
+
+ return okay;
+}
+#endif
+
+static bool
+tpm_check_capabilities(void)
+{
+ uint32_t prop_startup, prop_permanent;
+
+ /* Check PropertyStartupClear (TPM2_PT_STARTUP_CLEAR) */
+ if (!tpm_get_tpm_property(TPM2_PT_STARTUP_CLEAR, &prop_startup)) {
+ error("Failed to get PropertyStartupClear\n");
+ return false;
+ }
+
+ if ((prop_startup & TPMA_STARTUP_CLEAR_SHENABLE) == 0) {
+ error("Storage hierarchy not enabled\n");
+ return false;
+ }
+
+ if ((prop_startup & TPMA_STARTUP_CLEAR_EHENABLE) == 0) {
+ error("Endorsement hierarchy not enabled\n");
+ return false;
+ }
+
+ /* Check PropertyPermanent (TPM2_PT_PERMANENT) */
+ if (!tpm_get_tpm_property(TPM2_PT_PERMANENT, &prop_permanent)) {
+ error("Failed to get PropertyPermanent\n");
+ return false;
+ }
+
+ if ((prop_permanent & TPMA_PERMANENT_OWNERAUTHSET) != 0) {
+ error("TPM2 Owner Authorization set\n");
+ return false;
+ }
+
+ if ((prop_permanent & TPMA_PERMANENT_ENDORSEMENTAUTHSET) != 0) {
+ error("TPM2 Endorsement Authorization set\n");
+ return false;
+ }
+
+ if ((prop_permanent & TPMA_PERMANENT_LOCKOUTAUTHSET) != 0) {
+ error("TPM2 Lockout Authorization set\n");
+ return false;
+ }
+
+ if ((prop_permanent & TPMA_PERMANENT_INLOCKOUT) != 0) {
+ error("TPM2 in lockout\n");
+ return false;
+ }
+
+#ifdef TPM2_CAP_AUTH_POLICIES
+ /*
+ * Ensure that there is no authorization policy associated with the
+ * following hierarchies: TPM2_RH_LOCKOUT, TPM2_RH_OWNER, and
+ * TPM2_RH_ENDORSEMENT
+ *
+ * Some older TPM may not support TPM2_CAP_AUTH_POLICIES, so the
+ * following checks are optional.
+ */
+ if (!tpm_check_auth_policies(TPM2_RH_LOCKOUT)) {
+ warning("Error from LockOut handle\n");
+ goto skip_auth_policies;
+ }
+
+ if (!tpm_check_auth_policies(TPM2_RH_OWNER)) {
+ warning("Error from Owner handle\n");
+ goto skip_auth_policies;
+ }
+
+ if (!tpm_check_auth_policies(TPM2_RH_ENDORSEMENT)) {
+ warning("Error from Endorsement handle\n");
+ goto skip_auth_policies;
+ }
+
+skip_auth_policies:
+#endif
+
+ return true;
+}
+
bool
tpm_selftest(bool fulltest)
{
ESYS_CONTEXT *esys_ctx = tss_esys_context();
TSS2_RC rc;
+ /* TPM self test */
rc = Esys_SelfTest(esys_ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, fulltest);
- return tss_check_error(rc, "TPM self test failed");
+ if (rc != TSS2_RC_SUCCESS)
+ return tss_check_error(rc, "TPM self test failed");
+
+ /* Capability check */
+ if(!tpm_check_capabilities())
+ return false;
+
+ return true;
}
bool
--
2.51.0
From 3fb4199db23d1e6d20b6eb073ede0c535c94a3e3 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 26 Sep 2025 15:27:25 +0800
Subject: [PATCH 2/3] Add SRK template test to self-test
Add the RSA and ECC SRK template test to self-test.
Signed-off-by: Gary Lin <glin@suse.com>
---
src/pcr-policy.c | 4 ++--
src/tpm.c | 34 ++++++++++++++++++++++++++++++++++
src/tpm.h | 3 +++
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/src/pcr-policy.c b/src/pcr-policy.c
index e5d1bc9..3c08775 100644
--- a/src/pcr-policy.c
+++ b/src/pcr-policy.c
@@ -62,7 +62,7 @@ struct target_platform {
const stored_key_t *public_key_file);
};
-static TPM2B_PUBLIC RSA_SRK_template = {
+TPM2B_PUBLIC RSA_SRK_template = {
.size = sizeof(TPMT_PUBLIC),
.publicArea = {
.type = TPM2_ALG_RSA,
@@ -88,7 +88,7 @@ static TPM2B_PUBLIC RSA_SRK_template = {
}
};
-static TPM2B_PUBLIC ECC_SRK_template = {
+TPM2B_PUBLIC ECC_SRK_template = {
.size = sizeof(TPMT_PUBLIC),
.publicArea = {
.type = TPM2_ALG_ECC,
diff --git a/src/tpm.c b/src/tpm.c
index fdfffc8..b9047dc 100644
--- a/src/tpm.c
+++ b/src/tpm.c
@@ -267,6 +267,36 @@ skip_auth_policies:
return true;
}
+static bool
+tpm_check_srk(void)
+{
+ ESYS_CONTEXT *esys_ctx = tss_esys_context();
+ TPMT_PUBLIC_PARMS parms = {0};
+ TSS2_RC rc;
+
+ /* Test RSA SRK */
+ parms.type = TPM2_ALG_RSA;
+ memcpy(&parms.parameters, &RSA_SRK_template.publicArea.parameters,
+ sizeof(TPMU_PUBLIC_PARMS));
+
+ rc = Esys_TestParms(esys_ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parms);
+ if (rc != TSS2_RC_SUCCESS)
+ return tss_check_error(rc, "RSA SRK test failed");
+
+ memset(&parms, 0, sizeof(TPMT_PUBLIC_PARMS));
+
+ /* Test ECC SRK */
+ parms.type = TPM2_ALG_ECC;
+ memcpy(&parms.parameters, &ECC_SRK_template.publicArea.parameters,
+ sizeof(TPMU_PUBLIC_PARMS));
+
+ rc = Esys_TestParms(esys_ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &parms);
+ if (rc != TSS2_RC_SUCCESS)
+ return tss_check_error(rc, "ECC SRK test failed");
+
+ return true;
+}
+
bool
tpm_selftest(bool fulltest)
{
@@ -282,6 +312,10 @@ tpm_selftest(bool fulltest)
if(!tpm_check_capabilities())
return false;
+ /* SRK template test */
+ if (!tpm_check_srk())
+ return false;
+
return true;
}
diff --git a/src/tpm.h b/src/tpm.h
index 50ae203..8a5ef2d 100644
--- a/src/tpm.h
+++ b/src/tpm.h
@@ -28,6 +28,9 @@
extern uint32_t esys_tr_rh_null;
extern uint32_t esys_tr_rh_owner;
+extern TPM2B_PUBLIC RSA_SRK_template;
+extern TPM2B_PUBLIC ECC_SRK_template;
+
extern ESYS_CONTEXT * tss_esys_context(void);
extern void tss_print_error(int rc, const char *msg);
--
2.51.0
From b7aadd51b1ca8b1957580f6a527c4b3b30e30ec7 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 26 Sep 2025 15:30:00 +0800
Subject: [PATCH 3/3] Fix a typo in tpm_rsa_bits_test()
Fix a typo in the error message of tpm_rsa_bits_test()
Signed-off-by: Gary Lin <glin@suse.com>
---
src/tpm.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/tpm.c b/src/tpm.c
index b9047dc..2b52ef0 100644
--- a/src/tpm.c
+++ b/src/tpm.c
@@ -343,9 +343,8 @@ tpm_rsa_bits_test(unsigned int rsa_bits)
ESYS_TR_NONE, &rsa_parms);
if (rc == TSS2_RC_SUCCESS)
okay = true;
- else if (rc != (TPM2_RC_VALUE | TPM2_RC_P | TPM2_RC_1)) {
- tss_check_error(rc, "Esys_CreatePrimary failed");
- }
+ else if (rc != (TPM2_RC_VALUE | TPM2_RC_P | TPM2_RC_1))
+ tss_check_error(rc, "Esys_TestParms failed");
return okay;
}
--
2.51.0