Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package grub2 for openSUSE:Factory checked in at 2023-11-22 18:54:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grub2 (Old) and /work/SRC/openSUSE:Factory/.grub2.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "grub2" Wed Nov 22 18:54:05 2023 rev:308 rq:1127831 version:2.12~rc1 Changes: -------- --- /work/SRC/openSUSE:Factory/grub2/grub2.changes 2023-11-17 20:49:30.945088883 +0100 +++ /work/SRC/openSUSE:Factory/.grub2.new.25432/grub2.changes 2023-11-22 18:54:09.418581619 +0100 @@ -1,0 +2,9 @@ +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 + +------------------------------------------------------------------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ 0003-protectors-Add-TPM2-Key-Protector.patch ++++++ --- /var/tmp/diff_new_pack.vlU3tr/_old 2023-11-22 18:54:12.598698329 +0100 +++ /var/tmp/diff_new_pack.vlU3tr/_new 2023-11-22 18:54:12.598698329 +0100 @@ -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 @@ 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 @@ +} 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 @@ + .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 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 @@ + &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 @@ + 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 @@ + 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 @@ + 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 @@ + &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 @@ + &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 @@ + + 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 @@ +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 @@ + */ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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; + } + ++++++ 0004-tpm2-Support-authorized-policy.patch ++++++ --- /var/tmp/diff_new_pack.vlU3tr/_old 2023-11-22 18:54:12.634699650 +0100 +++ /var/tmp/diff_new_pack.vlU3tr/_new 2023-11-22 18:54:12.638699797 +0100 @@ -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 @@ + 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 @@ + &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 @@ 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; ++++++ 0005-util-grub-protect-Add-new-tool.patch ++++++ --- /var/tmp/diff_new_pack.vlU3tr/_old 2023-11-22 18:54:12.658700531 +0100 +++ /var/tmp/diff_new_pack.vlU3tr/_new 2023-11-22 18:54:12.662700677 +0100 @@ -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 @@ 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 @@ + 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 @@ 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 @@ 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 @@ + 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 @@ + 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 @@ + 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 @@ + .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 @@ + .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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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")); -+ -+ *srk = TPM2_SRK_HANDLE; -+ return GRUB_ERR_NONE; -+ } ++ /* 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; ++ } + -+ /* 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 @@ + &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 @@ + } + 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 @@ + &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 @@ + 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 @@ + 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 @@ + 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 @@ + 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,4 +1615,7 @@ + + return err; +} +-- +2.35.3 +