SHA256
1
0
forked from pool/grub2

Accepting request 1127240 from home:gary_lin:branches:Base:System

- Update the TPM2 patches to skip the persistent SRK handle if not
  specified and improve the error messages
  + 0003-protectors-Add-TPM2-Key-Protector.patch
  + 0005-util-grub-protect-Add-new-tool.patch
  + 0004-tpm2-Support-authorized-policy.patch

OBS-URL: https://build.opensuse.org/request/show/1127240
OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=475
This commit is contained in:
Michael Chang 2023-11-21 06:44:02 +00:00 committed by Git OBS Bridge
parent d2d2c88ea6
commit 82ab887bba
4 changed files with 247 additions and 244 deletions

View File

@ -1,7 +1,7 @@
From 0ecf5ff31a89e061aef5e40ee68f8828e7b5eb81 Mon Sep 17 00:00:00 2001
From 2a63876ca714d177f919b2392d8efa0e3bd3ebe2 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:55 -0800
Subject: [PATCH v6 10/20] protectors: Add TPM2 Key Protector
Subject: [PATCH v7 10/20] protectors: Add TPM2 Key Protector
The TPM2 key protector is a module that enables the automatic retrieval
of a fully-encrypted disk's unlocking key from a TPM 2.0.
@ -111,20 +111,20 @@ parameters.
Currently, there is only one supported policy command: TPM2_PolicyPCR.
The command set can be extended to support advanced features, such as
as authorized policy, in the future.
authorized policy, in the future.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/Makefile.core.def | 13 +
grub-core/tpm2/args.c | 177 +++++
grub-core/tpm2/module.c | 1040 +++++++++++++++++++++++++++++
grub-core/tpm2/module.c | 1028 +++++++++++++++++++++++++++++
grub-core/tpm2/tpm2key.asn | 31 +
grub-core/tpm2/tpm2key.c | 440 ++++++++++++
grub-core/tpm2/tpm2key.c | 447 +++++++++++++
grub-core/tpm2/tpm2key_asn1_tab.c | 41 ++
include/grub/tpm2/internal/args.h | 41 ++
include/grub/tpm2/tpm2key.h | 83 +++
8 files changed, 1866 insertions(+)
8 files changed, 1861 insertions(+)
create mode 100644 grub-core/tpm2/args.c
create mode 100644 grub-core/tpm2/module.c
create mode 100644 grub-core/tpm2/tpm2key.asn
@ -342,10 +342,10 @@ index 000000000..274f4fef0
+}
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
new file mode 100644
index 000000000..9605ddbc7
index 000000000..df0727215
--- /dev/null
+++ b/grub-core/tpm2/module.c
@@ -0,0 +1,1040 @@
@@ -0,0 +1,1028 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
@ -477,8 +477,7 @@ index 000000000..9605ddbc7
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("In SRK mode, the SRK handle if the SRK is persistent "
+ "(default is 0x81000001)."),
+ N_("In SRK mode, the SRK handle if the SRK is persistent."),
+ },
+ {
+ .longarg = "asymmetric",
@ -519,51 +518,58 @@ index 000000000..9605ddbc7
+ grub_off_t file_size;
+ void *read_buffer;
+ grub_off_t read_n;
+ grub_err_t err;
+
+ /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9
+ * otherwise we'll never be able to predict the value of PCR9 at unseal time */
+ file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE);
+ if (file == NULL)
+ {
+ grub_dprintf ("tpm2", "Could not open file: %s\n", filepath);
+ /* grub_file_open sets grub_errno on error, and if we do no unset it,
+ * future calls to grub_file_open will fail (and so will anybody up the
+ * stack who checks the value, if any). */
+ grub_errno = GRUB_ERR_NONE;
+ return GRUB_ERR_FILE_NOT_FOUND;
+ /* Push errno from grub_file_open() into the error message stack */
+ grub_error_push();
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("Could not open file: %s\n"),
+ filepath);
+ goto error;
+ }
+
+ file_size = grub_file_size (file);
+ if (file_size == 0)
+ {
+ grub_dprintf ("tpm2", "Could not read file size: %s\n", filepath);
+ grub_file_close (file);
+ return GRUB_ERR_OUT_OF_RANGE;
+ err = grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Could not read file size: %s"),
+ filepath);
+ goto error;
+ }
+
+ read_buffer = grub_malloc (file_size);
+ if (read_buffer == NULL)
+ {
+ grub_dprintf ("tpm2", "Could not allocate buffer for %s.\n", filepath);
+ grub_file_close (file);
+ return GRUB_ERR_OUT_OF_MEMORY;
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ N_("Could not allocate buffer for %s"),
+ filepath);
+ goto error;
+ }
+
+ read_n = grub_file_read (file, read_buffer, file_size);
+ if (read_n != file_size)
+ {
+ grub_dprintf ("tpm2", "Could not retrieve file contents: %s\n", filepath);
+ grub_free (read_buffer);
+ grub_file_close (file);
+ return GRUB_ERR_FILE_READ_ERROR;
+ err = grub_error (GRUB_ERR_FILE_READ_ERROR,
+ N_("Could not retrieve file contents: %s"),
+ filepath);
+ goto error;
+ }
+
+ grub_file_close (file);
+
+ *buffer = read_buffer;
+ *buffer_size = file_size;
+
+ return GRUB_ERR_NONE;
+ err = GRUB_ERR_NONE;
+
+error:
+ grub_file_close (file);
+
+ return err;
+}
+
+static grub_err_t
@ -575,12 +581,9 @@ index 000000000..9605ddbc7
+
+ grub_tpm2_buffer_init (&buf);
+ if (sealed_key_size > buf.cap)
+ {
+ grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer "
+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n",
+ sealed_key_size, buf.cap);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Sealed key larger than %" PRIuGRUB_SIZE " bytes"),
+ buf.cap);
+
+ grub_memcpy (buf.data, sealed_key, sealed_key_size);
+ buf.size = sealed_key_size;
@ -589,11 +592,7 @@ index 000000000..9605ddbc7
+ grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private);
+
+ if (buf.error)
+ {
+ grub_dprintf ("tpm2", "Could not unmarshal sealed key file, it is likely "
+ "malformed.\n");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Malformed TPM wire key file"));
+
+ return GRUB_ERR_NONE;
+}
@ -668,10 +667,9 @@ index 000000000..9605ddbc7
+ grub_tpm2_buffer_init (&buf);
+ if (sealed_pub_size + sealed_priv_size > buf.cap)
+ {
+ grub_dprintf ("tpm2", "Sealed key is larger than decode buffer "
+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n",
+ sealed_pub_size, buf.cap);
+ err = GRUB_ERR_BAD_ARGUMENT;
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Sealed key larger than %" PRIuGRUB_SIZE " bytes"),
+ buf.cap);
+ goto error;
+ }
+
@ -685,9 +683,7 @@ index 000000000..9605ddbc7
+
+ if (buf.error)
+ {
+ grub_dprintf ("tpm2", "Could not unmarshal sealed key, it is likely "
+ "malformed.\n");
+ err = GRUB_ERR_BAD_ARGUMENT;
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Malformed TPM 2.0 key file"));
+ goto error;
+ }
+
@ -720,21 +716,19 @@ index 000000000..9605ddbc7
+ TPM2B_NAME srkName = { 0 };
+ TPM_HANDLE srkHandle;
+
+ /* Find SRK */
+ rc = TPM2_ReadPublic (ctx->srk, NULL, &public);
+ if (rc == TPM_RC_SUCCESS)
+ if (ctx->srk != 0)
+ {
+ *srk = ctx->srk;
+ return GRUB_ERR_NONE;
+ }
+ /* Find SRK */
+ rc = TPM2_ReadPublic (ctx->srk, NULL, &public);
+ if (rc == TPM_RC_SUCCESS)
+ {
+ *srk = ctx->srk;
+ return GRUB_ERR_NONE;
+ }
+
+ /* The handle exists but its public area could not be read. */
+ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE)
+ {
+ grub_dprintf ("tpm2", "The SRK handle (0x%x) exists on the TPM but its "
+ "public area could not be read (TPM2_ReadPublic "
+ "failed with TSS/TPM error %u).\n", ctx->srk, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to retrieve SRK (TPM2_ReadPublic: 0x%x)"),
+ rc);
+ }
+
+ /* Create SRK */
@ -768,7 +762,7 @@ index 000000000..9605ddbc7
+ inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
+ }
+ else
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown SRK algorithm"));
+
+ rc = TPM2_CreatePrimary (parent, &authCommand, &inSensitive, &inPublic,
+ &outsideInfo, &creationPcr, &srkHandle, &outPublic,
@ -931,8 +925,8 @@ index 000000000..9605ddbc7
+ &session, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to start auth session (TPM2_StartAuthSession: "
+ "0x%x)"), rc);
+ N_("Failed to start auth session (TPM2_StartAuthSession: 0x%x)"),
+ rc);
+
+ /* Enforce the policy command sequence */
+ err = grub_tpm2_protector_enforce_policy_seq (policy_seq, session);
@ -944,9 +938,9 @@ index 000000000..9605ddbc7
+ rc = TPM2_Unseal (sealed_handle, &authCmd, &data, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal: 0x%x)"),
+ rc);
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to unseal sealed key (TPM2_Unseal: 0x%x)"),
+ rc);
+ goto error;
+ }
+
@ -954,8 +948,8 @@ index 000000000..9605ddbc7
+ key_out = grub_malloc (data.size);
+ if (key_out == NULL)
+ {
+ err = GRUB_ERR_OUT_OF_MEMORY;
+ grub_error (err, N_("No memory left to allocate unlock key buffer"));
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ N_("No memory left to allocate unlock key buffer"));
+ goto error;
+ }
+
@ -999,7 +993,7 @@ index 000000000..9605ddbc7
+ err = grub_tpm2_protector_srk_read_file (ctx->tpm2key, &file_bytes,
+ &file_size);
+ if (err != GRUB_ERR_NONE)
+ return grub_error (err, N_("Failed to read key file %s"), ctx->tpm2key);
+ return err;
+
+ err = grub_tpm2_protector_srk_unmarshal_tpm2key (file_bytes,
+ file_size,
@ -1008,29 +1002,21 @@ index 000000000..9605ddbc7
+ &parent_handle,
+ &sealed_key);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in "
+ "TPM 2.0 Key File format"));
+ goto exit1;
+ }
+ goto exit1;
+ }
+ else
+ {
+ err = grub_tpm2_protector_srk_read_file (ctx->keyfile, &file_bytes,
+ &file_size);
+ if (err != GRUB_ERR_NONE)
+ return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile);
+ return err;
+
+ parent_handle = TPM_RH_OWNER;
+ err = grub_tpm2_protector_srk_unmarshal_keyfile (file_bytes,
+ file_size,
+ &sealed_key);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in "
+ "TPM wire format"));
+ goto exit1;
+ }
+ goto exit1;
+ }
+
+ /* Get the SRK to unseal the sealed key */
@ -1044,11 +1030,16 @@ index 000000000..9605ddbc7
+ &sealed_handle, &name, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to load sealed key (TPM2_Load: 0x%x)"), rc);
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to load sealed key (TPM2_Load: 0x%x)"),
+ rc);
+ goto exit2;
+ }
+
+ /*
+ * Set err to an error code to trigger the standalone policy sequence
+ * if there is no authpolicy sequence
+ */
+ err = GRUB_ERR_READ_ERROR;
+
+ /* Iterate the authpolicy sequence to find one that unseals the key */
@ -1200,9 +1191,6 @@ index 000000000..9605ddbc7
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK)
+ {
+ if (!ctx->srk)
+ ctx->srk = TPM2_SRK_HANDLE;
+
+ if (!ctx->asymmetric)
+ {
+ ctx->asymmetric = TPM_ALG_RSA;
@ -1425,10 +1413,10 @@ index 000000000..e3b6a03e0
+END
diff --git a/grub-core/tpm2/tpm2key.c b/grub-core/tpm2/tpm2key.c
new file mode 100644
index 000000000..62f6d865b
index 000000000..a26c287c9
--- /dev/null
+++ b/grub-core/tpm2/tpm2key.c
@@ -0,0 +1,440 @@
@@ -0,0 +1,447 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2023 SUSE LLC
@ -1543,24 +1531,29 @@ index 000000000..62f6d865b
+ */
+ ret = asn1_array2tree (tpm2key_asn1_tab, &tpm2key_asn1, NULL);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to parse TPM2KEY ASN.1 array"));
+
+ ret = asn1_create_element (tpm2key_asn1, "TPM2KEY.TPMKey", &tpm2key);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to create TPM2KEY.TPMKey"));
+
+ ret = asn1_der_decoding (&tpm2key, data, size, NULL);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to decode TPM2KEY DER"));
+
+ /* Check if 'type' is Sealed Key or not */
+ ret = asn1_allocate_and_read (tpm2key, "type", &type_oid, &type_oid_size);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_BAD_FILE_TYPE;
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ N_("Not a valid TPM2KEY file"));
+
+ if (grub_memcmp (sealed_key_oid, type_oid, type_oid_size) != 0)
+ {
+ err = GRUB_ERR_BAD_FILE_TYPE;
+ err = grub_error (GRUB_ERR_BAD_FILE_TYPE,
+ N_("Not a valid TPM2KEY file"));
+ goto error;
+ }
+
@ -1568,7 +1561,7 @@ index 000000000..62f6d865b
+ ret = asn1_allocate_and_read (tpm2key, "emptyAuth", &empty_auth, &empty_auth_size);
+ if (ret != ASN1_SUCCESS || grub_strncmp ("TRUE", empty_auth, empty_auth_size) != 0)
+ {
+ err = GRUB_ERR_BAD_ARGUMENT;
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("emptyAuth not TRUE"));
+ goto error;
+ }
+
@ -1576,7 +1569,8 @@ index 000000000..62f6d865b
+ ret = asn1_read_value (tpm2key, "secret", NULL, &tmp_size);
+ if (ret != ASN1_ELEMENT_NOT_FOUND)
+ {
+ err = GRUB_ERR_BAD_ARGUMENT;
+ err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("\"secret\" not allowed for Sealed Key"));
+ goto error;
+ }
+
@ -1608,14 +1602,14 @@ index 000000000..62f6d865b
+ int ret;
+
+ if (parent == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer detected"));
+
+ if (tpm2key == NULL)
+ return GRUB_ERR_READ_ERROR;
+ return grub_error (GRUB_ERR_READ_ERROR, N_("Invalid parent node"));
+
+ ret = asn1_read_uint32 (tpm2key, "parent", parent);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_READ_ERROR;
+ return grub_error (GRUB_ERR_READ_ERROR, N_("Failed to retrieve parent"));
+
+ return GRUB_ERR_NONE;
+}
@ -1626,14 +1620,16 @@ index 000000000..62f6d865b
+ int ret;
+
+ if (name == NULL || data == NULL || size == NULL)
+ return GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter(s)"));
+
+ if (tpm2key == NULL)
+ return GRUB_ERR_READ_ERROR;
+ return grub_error (GRUB_ERR_READ_ERROR, N_("Invalid %s node"), name);
+
+ ret = asn1_allocate_and_read (tpm2key, name, data, size);
+ if (ret != ASN1_SUCCESS)
+ return GRUB_ERR_READ_ERROR;
+ return grub_error (GRUB_ERR_READ_ERROR,
+ N_("Failed to retrieve %s"),
+ name);
+
+ return GRUB_ERR_NONE;
+}
@ -1764,9 +1760,7 @@ index 000000000..62f6d865b
+ return GRUB_ERR_NONE;
+ }
+ else if (ret != ASN1_SUCCESS)
+ {
+ return GRUB_ERR_READ_ERROR;
+ }
+ return grub_error (GRUB_ERR_READ_ERROR, N_("Failed to retrieve policy"));
+
+ return GRUB_ERR_NONE;
+}
@ -1806,13 +1800,12 @@ index 000000000..62f6d865b
+ return GRUB_ERR_NONE;
+ }
+ else if (ret != ASN1_SUCCESS)
+ {
+ return GRUB_ERR_READ_ERROR;
+ }
+ return grub_error (GRUB_ERR_READ_ERROR, N_("Failed to retrieve authPolicy"));
+
+ /* Limit the number of authPolicy elements to two digits (99) */
+ if (authpol_n > 100 || authpol_n < 1)
+ return GRUB_ERR_OUT_OF_RANGE;
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Invalid number of autoPolicy elements"));
+
+ /*
+ * Iterate the authPolicy elements backwards since grub_list_push() prepends
@ -1822,7 +1815,8 @@ index 000000000..62f6d865b
+ authpol = grub_zalloc (sizeof (struct tpm2key_authpolicy));
+ if (authpol == NULL)
+ {
+ err = GRUB_ERR_OUT_OF_MEMORY;
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ N_("Failed to allocate memory for authPolicy"));
+ goto error;
+ }
+ grub_snprintf (authpol_pol, AUTHPOLICY_POL_MAX, "authPolicy.?%d.Policy", i);
@ -1830,7 +1824,8 @@ index 000000000..62f6d865b
+ ret = tpm2key_get_policy_seq (tpm2key, authpol_pol, &authpol->policy_seq);
+ if (ret != ASN1_SUCCESS)
+ {
+ err = GRUB_ERR_READ_ERROR;
+ err = grub_error (GRUB_ERR_READ_ERROR,
+ N_("Failed to retrieve policy from authPolicy"));
+ goto error;
+ }
+

View File

@ -1,31 +1,73 @@
From d6e2d32d53d9a1aac2383fc6c075f3827111b643 Mon Sep 17 00:00:00 2001
From 542c4fc6e067e04e8b96f798882ae968c59f4948 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Thu, 6 Apr 2023 16:00:25 +0800
Subject: [PATCH 4/4] tpm2: Support authorized policy
Subject: [PATCH v7 16/20] tpm2: Support authorized policy
TPM2_PolicyAuthorize is the key command to support authorized policy
which allows the users to sign TPM policies with their own keys.
This commit handles the TPM2_PolicyAuthorize command from the key file
in TPM 2.0 Key File format.
Per TPM 2.0 Key File(*), CommandPolicy for TPM2_PolicyAuthorize
TPM2_PolicyAuthorize is the essential command to support authorized
policy which allows the users to sign TPM policies with their own keys.
Per TPM 2.0 Key File(*1), CommandPolicy for TPM2_PolicyAuthorize
comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and
'TPMT_SIGNATURE signature'. This commit unmarshals those data
structures, fetches the current policy digest, hashes the policy digest
with the hash algorithm written in 'signature', and then verifies
'signature' with 'pubkey'. If everything goes well, TPM2_PolicyAuthorize
is invoked to authorize the signed policy.
'TPMT_SIGNATURE signature'. To verify the signature, the current policy
digest is hashed with the hash algorithm written in 'signature', and then
'signature' is verified with the hashed policy digest and 'pubkey'. Once
TPM accepts 'signature', TPM2_PolicyAuthorize is invoked to authorize the
signed policy.
(*) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
To create the key file with authorized policy, here are the pcr-oracle(*2)
commands:
# Generate the RSA key and create the authorized policy file
$ pcr-oracle \
--rsa-generate-key \
--private-key policy-key.pem \
--auth authorized.policy \
create-authorized-policy 0,2,4,7,9
# Seal the secret with the authorized policy
$ pcr-oracle \
--key-format tpm2.0 \
--auth authorized.policy \
--input disk-secret.txt \
--output sealed.key \
seal-secret
# Sign the predicted PCR policy
$ pcr-oracle \
--key-format tpm2.0 \
--private-key policy-key.pem \
--from eventlog \
--stop-event "grub-file=grub.cfg" \
--after \
--input sealed.key \
--output sealed.tpm \
sign 0,2,4,7.9
Then specify the key file and the key protector to grub.cfg in the EFI
system partition:
tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u <PART_UUID> -P tpm2
For any change in the boot components, just run the 'sign' command again
to update the signature in sealed.tpm, and TPM can unseal the key file
with the updated PCR policy.
(*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*2) https://github.com/okirch/pcr-oracle
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/tpm2/module.c | 98 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
grub-core/tpm2/module.c | 84 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index 5274296b7..e5235c2ac 100644
index df0727215..0cbfd06e8 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -454,6 +454,101 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session,
@@ -453,6 +453,87 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session,
return GRUB_ERR_NONE;
}
@ -49,59 +91,45 @@ index 5274296b7..e5235c2ac 100644
+ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
+ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
+ if (cmd_buf->error != 0)
+ {
+ err = GRUB_ERR_BAD_ARGUMENT;
+ return grub_error (err, N_("Failed to unmarshal the buffer for "
+ "TPM2_PolicyAuthorize"));
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to unmarshal the buffer for TPM2_PolicyAuthorize"));
+
+ /* Retrieve Policy Digest */
+ rc = TPM2_PolicyGetDigest (session, NULL, &pcr_policy, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to get policy digest (TPM error: 0x%x)."),
+ rc);
+ return err;
+ }
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to get policy digest (TPM2_PolicyGetDigest: 0x%x)."),
+ rc);
+
+ /* Calculate the digest of the polcy for VerifySignature */
+ sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature);
+ if (sig_hash == TPM_ALG_NULL)
+ {
+ err = GRUB_ERR_BAD_ARGUMENT;
+ grub_error (err, N_("Failed to get the hash algorithm of the signature"));
+ return err;
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Failed to get the hash algorithm of the signature"));
+
+ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, sig_hash,
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to create PCR policy hash (TPM2_Hash failed "
+ "with TSS/TPM error %u)"), rc);
+ return err;
+ }
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to create PCR policy hash (TPM2_Hash: 0x%x)"),
+ rc);
+
+ /* Load the public key */
+ rc = TPM2_LoadExternal (NULL, NULL, &pubkey, TPM_RH_OWNER,
+ &pubkey_handle, &pubname, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to load public key (TPM2_LoadExternal failed "
+ "with TSS/TPM error %u)"), rc);
+ return err;
+ }
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to load public key (TPM2_LoadExternal: 0x%x)"),
+ rc);
+
+ /* Verify the signature against the public key and the policy digest */
+ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to verify signature (TPM2_VerifySignature "
+ "failed with TSS/TPM error %u)"), rc);
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to verify signature (TPM2_VerifySignature: 0x%x)"),
+ rc);
+ goto error;
+ }
+
@ -110,9 +138,9 @@ index 5274296b7..e5235c2ac 100644
+ &verification_ticket, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize "
+ "failed with TSS/TPM error: 0x%u).\n"), rc);
+ err = grub_error (GRUB_ERR_BAD_DEVICE,
+ N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)"),
+ rc);
+ goto error;
+ }
+
@ -127,7 +155,7 @@ index 5274296b7..e5235c2ac 100644
static grub_err_t
grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION session)
{
@@ -473,6 +568,9 @@ grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSIO
@@ -472,6 +553,9 @@ grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSIO
case TPM_CC_PolicyPCR:
err = grub_tpm2_protector_policypcr (session, &buf);
break;

View File

@ -1,7 +1,7 @@
From e5a1c5fe660e74d99d33d7d28914e968077ae603 Mon Sep 17 00:00:00 2001
From 1116bc4b9a27aceaec53421e89eb887e6ad3aef8 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:57 -0800
Subject: [PATCH v6 12/20] util/grub-protect: Add new tool
Subject: [PATCH v7 12/20] util/grub-protect: Add new tool
To utilize the key protectors framework, there must be a way to protect
full-disk encryption keys in the first place. The grub-protect tool
@ -51,21 +51,21 @@ cryptomount -u <SDB1_UUID> -P tpm2
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
---
.gitignore | 2 +
Makefile.util.def | 22 +
configure.ac | 9 +
util/grub-protect.c | 1524 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1557 insertions(+)
util/grub-protect.c | 1492 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1525 insertions(+)
create mode 100644 util/grub-protect.c
Index: grub-2.12~rc1/Makefile.util.def
===================================================================
--- grub-2.12~rc1.orig/Makefile.util.def
+++ grub-2.12~rc1/Makefile.util.def
@@ -208,6 +208,28 @@ program = {
diff --git a/Makefile.util.def b/Makefile.util.def
index e89abb38f..f43c223b9 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -207,6 +207,28 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
+program = {
+ name = grub-protect;
+
+ common = grub-core/osdep/init.c;
@ -87,14 +87,13 @@ Index: grub-2.12~rc1/Makefile.util.def
+ enable = efi;
+};
+
+program = {
program = {
name = grub-mkrelpath;
mansection = 1;
Index: grub-2.12~rc1/configure.ac
===================================================================
--- grub-2.12~rc1.orig/configure.ac
+++ grub-2.12~rc1/configure.ac
diff --git a/configure.ac b/configure.ac
index c19779c14..9796e5f9b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,7 @@ grub_TRANSFORM([grub-mkpasswd-pbkdf2])
grub_TRANSFORM([grub-mkrelpath])
grub_TRANSFORM([grub-mkrescue])
@ -103,7 +102,7 @@ Index: grub-2.12~rc1/configure.ac
grub_TRANSFORM([grub-reboot])
grub_TRANSFORM([grub-script-check])
grub_TRANSFORM([grub-set-default])
@@ -1992,6 +1993,14 @@ fi
@@ -2018,6 +2019,14 @@ fi
AC_SUBST([LIBZFS])
AC_SUBST([LIBNVPAIR])
@ -118,11 +117,12 @@ Index: grub-2.12~rc1/configure.ac
LIBS=""
AC_SUBST([FONT_SOURCE])
Index: grub-2.12~rc1/util/grub-protect.c
===================================================================
diff --git a/util/grub-protect.c b/util/grub-protect.c
new file mode 100644
index 000000000..c6d41ea40
--- /dev/null
+++ grub-2.12~rc1/util/grub-protect.c
@@ -0,0 +1,1524 @@
+++ b/util/grub-protect.c
@@ -0,0 +1,1492 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
@ -184,7 +184,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ GRUB_PROTECT_OPT_TPM2_SRK,
+ GRUB_PROTECT_OPT_TPM2_KEYFILE,
+ GRUB_PROTECT_OPT_TPM2_OUTFILE,
+ GRUB_PROTECT_OPT_TPM2_PERSIST,
+ GRUB_PROTECT_OPT_TPM2_EVICT,
+ GRUB_PROTECT_OPT_TPM2_TPM2KEY
+} grub_protect_opt;
@ -203,9 +202,8 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ GRUB_PROTECT_ARG_TPM2_SRK = 1 << 6,
+ GRUB_PROTECT_ARG_TPM2_KEYFILE = 1 << 7,
+ GRUB_PROTECT_ARG_TPM2_OUTFILE = 1 << 8,
+ GRUB_PROTECT_ARG_TPM2_PERSIST = 1 << 9,
+ GRUB_PROTECT_ARG_TPM2_EVICT = 1 << 10,
+ GRUB_PROTECT_ARG_TPM2_TPM2KEY = 1 << 11
+ GRUB_PROTECT_ARG_TPM2_EVICT = 1 << 9,
+ GRUB_PROTECT_ARG_TPM2_TPM2KEY = 1 << 10
+} grub_protect_arg_t;
+
+typedef enum grub_protect_protector
@ -237,7 +235,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ TPM_HANDLE tpm2_srk;
+ const char *tpm2_keyfile;
+ const char *tpm2_outfile;
+ int tpm2_persist;
+ int tpm2_evict;
+ int tpm2_tpm2key;
+};
@ -318,8 +315,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ .arg = "NUM",
+ .flags = 0,
+ .doc =
+ N_("The SRK handle if the SRK is to be made persistent "
+ "(default is 0x81000001)."),
+ N_("The SRK handle if the SRK is to be made persistent."),
+ .group = 0
+ },
+ {
@ -335,16 +331,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ .group = 0
+ },
+ {
+ .name = "tpm2-persist",
+ .key = GRUB_PROTECT_OPT_TPM2_PERSIST,
+ .arg = NULL,
+ .flags = 0,
+ .doc =
+ N_("Whether to persist the SRK onto the TPM, otherwise it is recreated "
+ "ephemerally during boot (default is to not persist it)."),
+ .group = 0
+ },
+ {
+ .name = "tpm2-evict",
+ .key = GRUB_PROTECT_OPT_TPM2_EVICT,
+ .arg = NULL,
@ -634,7 +620,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ rc = TPM2_PCR_Read (NULL, &pcr_sel, NULL, &pcr_sel_out, &pcr_values, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, _("Failed to read PCRs (TPM error: 0x%x).\n"), rc);
+ fprintf (stderr, _("Failed to read PCRs (TPM2_PCR_Read: 0x%x).\n"), rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
@ -711,7 +697,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr,
+ _("Failed to start trial policy session (TPM error: 0x%x).\n"),
+ _("Failed to start trial policy session (TPM2_StartAuthSession: 0x%x).\n"),
+ rc);
+ err = GRUB_ERR_BAD_DEVICE;
+ goto exit2;
@ -723,7 +709,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ rc = TPM2_PolicyPCR (session, NULL, &pcr_digest_in, &pcr_sel, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, _("Failed to submit PCR policy (TPM error: 0x%x).\n"),
+ fprintf (stderr, _("Failed to submit PCR policy (TPM2_PolicyPCR: 0x%x).\n"),
+ rc);
+ err = GRUB_ERR_BAD_DEVICE;
+ goto exit3;
@ -733,7 +719,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ rc = TPM2_PolicyGetDigest (session, NULL, &policy_digest, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, _("Failed to get policy digest (TPM error: 0x%x).\n"),
+ fprintf (stderr, _("Failed to get policy digest (TPM2_PolicyGetDigest: 0x%x).\n"),
+ rc);
+ err = GRUB_ERR_BAD_DEVICE;
+ goto exit3;
@ -772,26 +758,25 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ TPM2B_NAME srkName = { 0 };
+ TPM_HANDLE srkHandle;
+
+ /* Find SRK */
+ rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public);
+ if (rc == TPM_RC_SUCCESS)
+ if (args->tpm2_srk != 0)
+ {
+ if (args->tpm2_persist)
+ fprintf (stderr,
+ _("Warning: --tpm2-persist was specified but the SRK already "
+ "exists on the TPM. Continuing anyway...\n"));
+ /* Find SRK */
+ rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public);
+ if (rc == TPM_RC_SUCCESS)
+ {
+ printf (_("Read SRK from 0x%x\n"), args->tpm2_srk);
+ *srk = args->tpm2_srk;
+ return GRUB_ERR_NONE;
+ }
+
+ *srk = TPM2_SRK_HANDLE;
+ return GRUB_ERR_NONE;
+ }
+
+ /* The handle exists but its public area could not be read. */
+ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE)
+ {
+ fprintf (stderr,
+ _("The SRK exists on the TPM but its public area cannot be read "
+ "(TPM error: 0x%x).\n"), rc);
+ return GRUB_ERR_BAD_DEVICE;
+ /* The handle exists but its public area could not be read. */
+ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE)
+ {
+ fprintf (stderr,
+ _("Failed to retrieve SRK from 0x%x (TPM2_ReadPublic: 0x%x).\n"),
+ args->tpm2_srk, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+ }
+
+ /* Create SRK */
@ -836,12 +821,12 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ &srkName, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, _("Failed to create SRK (TPM error: 0x%x).\n"), rc);
+ fprintf (stderr, _("Failed to create SRK (TPM2_CreatePrimary: 0x%x).\n"), rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ /* Persist SRK */
+ if (args->tpm2_persist)
+ if (args->tpm2_srk != 0)
+ {
+ rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, &authCommand,
+ args->tpm2_srk, NULL);
@ -852,8 +837,8 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ }
+ else
+ fprintf (stderr,
+ _("Warning: Failed to persist SRK (TPM error: 0x%x\n). "
+ "Continuing anyway...\n"), rc);
+ _("Warning: Failed to persist SRK (0x%x) (TPM2_EvictControl: 0x%x\n). "
+ "Continuing anyway...\n"), args->tpm2_srk, rc);
+ }
+
+ /* Epilogue */
@ -891,7 +876,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ &pcr_sel, &outPrivate, &outPublic, NULL, NULL, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr, _("Failed to seal key (TPM error: 0x%x).\n"), rc);
+ fprintf (stderr, _("Failed to seal key (TPM2_Create: 0x%x).\n"), rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
@ -1202,7 +1187,7 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ if (rc != TPM_RC_SUCCESS)
+ {
+ fprintf (stderr,
+ _("Failed to evict SRK with handle 0x%x (TPM Error: 0x%x).\n"),
+ _("Failed to evict SRK with handle 0x%x (TPM2_EvictControl: 0x%x).\n"),
+ args->tpm2_srk, rc);
+ err = GRUB_ERR_BAD_DEVICE;
+ goto exit2;
@ -1269,9 +1254,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ args->tpm2_pcr_count = 1;
+ }
+
+ if (args->tpm2_srk == 0)
+ args->tpm2_srk = TPM2_SRK_HANDLE;
+
+ if (args->tpm2_asymmetric == TPM_ALG_ERROR)
+ {
+ args->tpm2_asymmetric = TPM_ALG_RSA;
@ -1319,19 +1301,16 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST)
+ if (args->tpm2_srk == 0)
+ {
+ fprintf (stderr,
+ _("--tpm2-persist is invalid when --action is 'remove'.\n"));
+ _("--tpm2-srk is not specified when --action is 'remove'.\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (args->tpm2_device == NULL)
+ args->tpm2_device = "/dev/tpm0";
+
+ if (args->tpm2_srk == 0)
+ args->tpm2_srk = TPM2_SRK_HANDLE;
+
+ break;
+
+ default:
@ -1497,17 +1476,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+ args->args |= GRUB_PROTECT_ARG_TPM2_OUTFILE;
+ break;
+
+ case GRUB_PROTECT_OPT_TPM2_PERSIST:
+ if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST)
+ {
+ fprintf (stderr, _("--tpm2-persist can only be specified once.\n"));
+ return EINVAL;
+ }
+
+ args->tpm2_persist = 1;
+ args->args |= GRUB_PROTECT_ARG_TPM2_PERSIST;
+ break;
+
+ case GRUB_PROTECT_OPT_TPM2_EVICT:
+ if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT)
+ {
@ -1647,3 +1615,6 @@ Index: grub-2.12~rc1/util/grub-protect.c
+
+ return err;
+}
--
2.35.3

View File

@ -1,3 +1,12 @@
-------------------------------------------------------------------
Thu Nov 16 06:39:46 UTC 2023 - Gary Ching-Pang Lin <glin@suse.com>
- Update the TPM2 patches to skip the persistent SRK handle if not
specified and improve the error messages
+ 0003-protectors-Add-TPM2-Key-Protector.patch
+ 0005-util-grub-protect-Add-new-tool.patch
+ 0004-tpm2-Support-authorized-policy.patch
-------------------------------------------------------------------
Tue Nov 14 07:52:41 UTC 2023 - Michael Chang <mchang@suse.com>