159 lines
5.8 KiB
Diff
159 lines
5.8 KiB
Diff
From 7ef1b9b357c803cb8e30bbbebd44494b2b5c9d09 Mon Sep 17 00:00:00 2001
|
|
From: Gary Lin <glin@suse.com>
|
|
Date: Thu, 6 Apr 2023 16:00:25 +0800
|
|
Subject: [PATCH] tpm2_key_protector: Support authorized policy
|
|
|
|
This commit handles the TPM2_PolicyAuthorize command from the key file
|
|
in TPM 2.0 Key File format.
|
|
|
|
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'. 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.
|
|
|
|
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 /boot/efi/efi/grub/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 -a RSA --tpm2key=(hd0,gpt1)/efi/grub/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>
|
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
.../commands/tpm2_key_protector/module.c | 70 +++++++++++++++++++
|
|
1 file changed, 70 insertions(+)
|
|
|
|
diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c
|
|
index 70d4d0df7..6b4b5d460 100644
|
|
--- a/grub-core/commands/tpm2_key_protector/module.c
|
|
+++ b/grub-core/commands/tpm2_key_protector/module.c
|
|
@@ -618,6 +618,73 @@ tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffe
|
|
return GRUB_ERR_NONE;
|
|
}
|
|
|
|
+static grub_err_t
|
|
+tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffer *cmd_buf)
|
|
+{
|
|
+ TPM2B_PUBLIC_t pubkey;
|
|
+ TPM2B_DIGEST_t policy_ref;
|
|
+ TPMT_SIGNATURE_t signature;
|
|
+ TPM2B_DIGEST_t pcr_policy;
|
|
+ TPM2B_DIGEST_t pcr_policy_hash;
|
|
+ TPMI_ALG_HASH_t sig_hash;
|
|
+ TPMT_TK_VERIFIED_t verification_ticket;
|
|
+ TPM_HANDLE_t pubkey_handle = 0;
|
|
+ TPM2B_NAME_t pubname;
|
|
+ TPM_RC_t rc;
|
|
+ grub_err_t err;
|
|
+
|
|
+ grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey);
|
|
+ grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref);
|
|
+ grub_Tss2_MU_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature);
|
|
+ if (cmd_buf->error != 0)
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal the buffer for TPM2_PolicyAuthorize");
|
|
+
|
|
+ /* Retrieve Policy Digest */
|
|
+ rc = grub_tpm2_policygetdigest (session, NULL, &pcr_policy, NULL);
|
|
+ if (rc != TPM_RC_SUCCESS)
|
|
+ return grub_error (GRUB_ERR_BAD_DEVICE, "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)
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to get the hash algorithm of the signature");
|
|
+
|
|
+ rc = grub_tpm2_hash (NULL, (TPM2B_MAX_BUFFER_t *) &pcr_policy, sig_hash,
|
|
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
|
|
+ if (rc != TPM_RC_SUCCESS)
|
|
+ return grub_error (GRUB_ERR_BAD_DEVICE, "failed to create PCR policy hash (TPM2_Hash: 0x%x)", rc);
|
|
+
|
|
+ /* Load the public key */
|
|
+ rc = grub_tpm2_loadexternal (NULL, NULL, &pubkey, TPM_RH_OWNER, &pubkey_handle, &pubname, NULL);
|
|
+ if (rc != TPM_RC_SUCCESS)
|
|
+ return grub_error (GRUB_ERR_BAD_DEVICE, "failed to load public key (TPM2_LoadExternal: 0x%x)", rc);
|
|
+
|
|
+ /* Verify the signature against the public key and the policy digest */
|
|
+ rc = grub_tpm2_verifysignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
|
|
+ &verification_ticket, NULL);
|
|
+ if (rc != TPM_RC_SUCCESS)
|
|
+ {
|
|
+ err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to verify signature (TPM2_VerifySignature: 0x%x)", rc);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ /* Authorize the signed policy with the public key and the verification ticket */
|
|
+ rc = grub_tpm2_policyauthorize (session, NULL, &pcr_policy, &policy_ref, &pubname,
|
|
+ &verification_ticket, NULL);
|
|
+ if (rc != TPM_RC_SUCCESS)
|
|
+ {
|
|
+ err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)", rc);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ err = GRUB_ERR_NONE;
|
|
+
|
|
+ error:
|
|
+ grub_tpm2_flushcontext (pubkey_handle);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
static grub_err_t
|
|
tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION_t session)
|
|
{
|
|
@@ -636,6 +703,9 @@ tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION_t s
|
|
case TPM_CC_PolicyPCR:
|
|
err = tpm2_protector_policypcr (session, &buf);
|
|
break;
|
|
+ case TPM_CC_PolicyAuthorize:
|
|
+ err = tpm2_protector_policyauthorize (session, &buf);
|
|
+ break;
|
|
default:
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown TPM Command: 0x%x", policy->cmd_code);
|
|
}
|
|
--
|
|
2.43.0
|
|
|