SHA256
1
0
forked from pool/grub2
grub2/0013-tpm2-support-unsealing-key-with-authorized-policy.patch
2023-02-09 08:57:28 +00:00

795 lines
27 KiB
Diff

From 47220d1ce8fffac3654454b8a981385133b7c23a Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Wed, 8 Feb 2023 11:26:25 +0800
Subject: [PATCH 13/13] tpm2: support unsealing key with authorized policy
To solve the PCR brittleness, TPM 2.0 allows the administrator to
'authorize' a new PCR policy, i.e. a new set of PCR values, to unseal
the existing key. This commit extends the SRK mode to support the
authorized policy mode to unseal the disk encryption key.
The usage of the authorized policy mode is very similar to the SRK mode
except two additional arguments: "-P" for the publicy key and "-S" for
the signed policy.
Example of the authorized policy mode:
tpm2_key_protector_init -m authpol -b sha256 -p 0,2,4,7 \
-k (hd0,gpt1)/boot/grub2/sealed.key \
-P (hd0,gpt1)/boot/grub2/pub.key \
-S (hd0,gpt1)/boot/grub2/pol.sig
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/tpm2/module.c | 614 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 602 insertions(+), 12 deletions(-)
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index c819ef616..8e1b14146 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -35,7 +35,8 @@ typedef enum grub_tpm2_protector_mode
{
GRUB_TPM2_PROTECTOR_MODE_UNSET,
GRUB_TPM2_PROTECTOR_MODE_SRK,
- GRUB_TPM2_PROTECTOR_MODE_NV
+ GRUB_TPM2_PROTECTOR_MODE_NV,
+ GRUB_TPM2_PROTECTOR_MODE_AUTHPOL
} grub_tpm2_protector_mode_t;
struct grub_tpm2_protector_context
@@ -47,6 +48,8 @@ struct grub_tpm2_protector_context
TPM_ALG_ID asymmetric;
TPM_ALG_ID bank;
const char *keyfile;
+ const char *pkfile;
+ const char *sigfile;
TPM_HANDLE srk;
TPM_HANDLE nv;
const char *efivar;
@@ -62,8 +65,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.arg = NULL,
.type = ARG_TYPE_STRING,
.doc =
- N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV "
- "Index ('nv')."),
+ N_("Unseal key using SRK ('srk') (default), retrieve it from an NV "
+ "Index ('nv'), or unseal key with a authorized policy ('authpol')."),
},
{
.longarg = "pcrs",
@@ -85,7 +88,7 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
N_("Bank of PCRs used to authorize key release: "
"SHA1, SHA256 (default), or SHA384."),
},
- /* SRK-mode options */
+ /* SRK-mode and Authorized Policy-mode options */
{
.longarg = "keyfile",
.shortarg = 'k',
@@ -93,8 +96,9 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.arg = NULL,
.type = ARG_TYPE_STRING,
.doc =
- N_("Required in SRK mode, path to the sealed key file to unseal using "
- "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key)."),
+ N_("Required in SRK and Authorized Policy mode, path to the sealed "
+ "key file to unseal using the TPM "
+ "(e.g., (hd0,gpt1)/boot/grub2/sealed_key)."),
},
{
.longarg = "srk",
@@ -103,8 +107,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.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 and Authorized Policy mode, the SRK handle if the SRK is "
+ "persistent (default is 0x81000001)."),
},
{
.longarg = "asymmetric",
@@ -113,7 +117,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.arg = NULL,
.type = ARG_TYPE_STRING,
.doc =
- N_("In SRK mode, the type of SRK: RSA (default) or ECC."),
+ N_("In SRK and Authorized Policy mode, the type of SRK: RSA "
+ "(default) or ECC."),
},
/* NV Index-mode options */
{
@@ -136,6 +141,26 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
.doc =
N_("Publish the unsealed key to the indicated UEFI variable."),
},
+ /* Authorized Policy-mode options */
+ {
+ .longarg = "pkfile",
+ .shortarg = 'P',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Public key file to verify the PCR policy signature"
+ "(e.g., (hd0,gpt1)/boot/grub2/pub.key)"),
+ },
+ {
+ .longarg = "sigfile",
+ .shortarg = 'S',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("PCR policy signature file (e.g., (hd0,gpt1)/boot/grub2/pol.sig)"),
+ },
/* End of list */
{0, 0, 0, 0, 0, 0}
};
@@ -199,6 +224,66 @@ grub_tpm2_protector_read_file (const char *filepath, void **buffer,
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_tpm2_protector_unmarshal_pkfile (void *pub_key,
+ grub_size_t pub_key_size,
+ TPM2B_PUBLIC *pk)
+{
+ struct grub_tpm2_buffer buf;
+
+ grub_tpm2_buffer_init (&buf);
+ if (pub_key_size > buf.cap)
+ {
+ grub_dprintf ("tpm2", "Public key file is larger than decode buffer "
+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", pub_key_size, buf.cap);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ grub_memcpy (buf.data, pub_key, pub_key_size);
+ buf.size = pub_key_size;
+
+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, pk);
+
+ if (buf.error)
+ {
+ grub_dprintf ("tpm2", "Could not unmarshal public key file, it is likely "
+ "malformed.\n");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_unmarshal_sigfile (void *sig,
+ grub_size_t sig_size,
+ TPMT_SIGNATURE *signature)
+{
+ struct grub_tpm2_buffer buf;
+
+ grub_tpm2_buffer_init (&buf);
+ if (sig_size > buf.cap)
+ {
+ grub_dprintf ("tpm2", "Signed PCR policy file is larger than decode buffer "
+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", sig_size, buf.cap);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ grub_memcpy (buf.data, sig, sig_size);
+ buf.size = sig_size;
+
+ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (&buf, signature);
+
+ if (buf.error)
+ {
+ grub_dprintf ("tpm2", "Could not unmarshal public key file, it is likely "
+ "malformed.\n");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
grub_tpm2_protector_unmarshal_keyfile (void *sealed_key,
grub_size_t sealed_key_size,
@@ -486,6 +571,433 @@ grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
N_("NV Index mode is not implemented yet"));
}
+static grub_err_t
+get_pcr_digest (const struct grub_tpm2_protector_context *ctx,
+ TPM2B_DIGEST *pcr_digest)
+{
+ TPM_RC rc;
+ TPML_PCR_SELECTION pcr_list_out = { 0 };
+ TPML_DIGEST pcr_values = { 0 };
+ grub_size_t pcr_digest_len;
+ TPM2B_AUTH auth = { 0 };
+ TPMI_DH_OBJECT sequence = 0;
+ TPMS_AUTH_COMMAND authCmd;
+ grub_uint8_t i;
+ TPM2B_DIGEST result_digest;
+ grub_err_t err = GRUB_ERR_INVALID_COMMAND;
+
+ if (!pcr_digest)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ /* PCR Read */
+ rc = TPM2_PCR_Read (NULL, &ctx->pcr_list, NULL, &pcr_list_out, &pcr_values, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ return grub_error (err, N_("Failed to read PCRs (TPM error: 0x%x)."), rc);
+ }
+
+ if ((pcr_list_out.count != ctx->pcr_list.count) ||
+ (ctx->pcr_list.pcrSelections[0].sizeOfSelect !=
+ pcr_list_out.pcrSelections[0].sizeOfSelect))
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ return grub_error (err, N_("Could not read all the specified PCRs."));
+ }
+
+ /* Check the hash algorithm */
+ switch (ctx->bank)
+ {
+ case TPM_ALG_SHA1:
+ pcr_digest_len = TPM_SHA1_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA256:
+ pcr_digest_len = TPM_SHA256_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA384:
+ pcr_digest_len = TPM_SHA384_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA512:
+ pcr_digest_len = TPM_SHA512_DIGEST_SIZE;
+ break;
+ default:
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ /* Start the hash sequence with an empty password (auth) */
+ rc = TPM2_HashSequenceStart (NULL, &auth, ctx->bank, &sequence, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ return grub_error (err,
+ N_("Failed to start hash sequence (TPM error: 0x%x)."),
+ rc);
+ }
+
+ /* Set up the password session with an empty password for TPM2_SequenceUpdate */
+ /* and TPM2_SequenceComplete */
+ grub_memset (&authCmd, 0, sizeof (TPMS_AUTH_COMMAND));
+ authCmd.sessionHandle = TPM_RS_PW;
+
+ for (i = 0; i < ctx->pcr_count; i++)
+ {
+ if (pcr_values.digests[i].size != pcr_digest_len)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err,
+ N_("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but got %u bytes.\n"),
+ pcr_digest_len, pcr_values.digests[i].size);
+ goto error;
+ }
+
+ rc = TPM2_SequenceUpdate (sequence, &authCmd,
+ (TPM2B_MAX_BUFFER *)&pcr_values.digests[i],
+ NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err,
+ N_("Failed to update hash sequence (TPM error: 0x%x)."),
+ rc);
+ goto error;
+ }
+ }
+
+ rc = TPM2_SequenceComplete (sequence, &authCmd, NULL, TPM_RH_NULL,
+ &result_digest, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err,
+ N_("Failed to complete hash sequence (TPM error: 0x%x)."),
+ rc);
+ goto error;
+ }
+
+ *pcr_digest = result_digest;
+ sequence = 0;
+ err = GRUB_ERR_NONE;
+
+error:
+
+ /* End the sequence if necessary */
+ if (sequence != 0)
+ {
+ grub_memset (&authCmd, 0, sizeof (TPMS_AUTH_COMMAND));
+ authCmd.sessionHandle = TPM_RS_PW;
+ TPM2_SequenceComplete (sequence, &authCmd, NULL, TPM_RH_NULL,
+ &result_digest, NULL, NULL);
+ }
+
+ return err;
+}
+
+static grub_err_t
+grub_tpm2_protector_authpol_digest (const struct grub_tpm2_protector_context *ctx,
+ TPM2B_DIGEST *digest)
+{
+ TPM_RC rc;
+ TPM2B_DIGEST pcr_digest;
+ TPM2B_NONCE nonce = { 0 };
+ TPMT_SYM_DEF symmetric = { 0 };
+ TPMI_SH_AUTH_SESSION session = 0;
+ TPM2B_DIGEST policy_digest = { 0 };
+ grub_err_t err;
+
+ err = get_pcr_digest (ctx, &pcr_digest);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ /* Start Trial Session to calculate the policy digest */
+ nonce.size = TPM_SHA256_DIGEST_SIZE;
+ symmetric.algorithm = TPM_ALG_NULL;
+
+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonce, NULL,
+ TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256,
+ &session, NULL, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err,
+ N_("Failed to start trial policy session (TPM error: 0x%x)."),
+ rc);
+ goto error;
+ }
+
+ /* PCR Policy */
+ rc = TPM2_PolicyPCR (session, NULL, &pcr_digest, &ctx->pcr_list, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, _("Failed to submit PCR policy (TPM error: 0x%x)."),
+ rc);
+ goto error;
+ }
+
+ /* Retrieve Policy Digest */
+ rc = TPM2_PolicyGetDigest (session, NULL, &policy_digest, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, _("Failed to get policy digest (TPM error: 0x%x)."),
+ rc);
+ goto error;
+ }
+
+ /* Epilogue */
+ *digest = policy_digest;
+ err = GRUB_ERR_NONE;
+
+error:
+ TPM2_FlushContext (session);
+
+ return err;
+}
+
+static grub_err_t
+grub_tpm2_protector_authpol_recover (const struct grub_tpm2_protector_context *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ TPM_RC rc;
+ TPM2B_DIGEST pcr_policy;
+ TPM2B_DIGEST pcr_policy_hash;
+ TPM2B_PUBLIC pub_key;
+ void *pub_key_bytes = NULL;
+ grub_size_t pub_key_size;
+ TPM2B_NAME pubname;
+ TPMT_SIGNATURE signature;
+ void *sig_bytes = NULL;
+ grub_size_t sig_size;
+ TPM2_SEALED_KEY sealed_key;
+ void *sealed_key_bytes = NULL;
+ grub_size_t sealed_key_size;
+ TPM_HANDLE pubkey_handle = 0;
+ TPM_HANDLE primary_handle = 0;
+ TPM_HANDLE sealed_key_handle = 0;
+ TPMT_SYM_DEF symmetric = { 0 };
+ TPM2B_NONCE nonceCaller = { 0 };
+ TPMI_SH_AUTH_SESSION session;
+ TPM2B_SENSITIVE_DATA data;
+ TPMS_AUTH_COMMAND authCmd = { 0 };
+ TPMT_TK_VERIFIED verification_ticket;
+ grub_uint8_t *key_out;
+ grub_err_t err;
+
+ /* Retrieve Public Key */
+ err = grub_tpm2_protector_read_file (ctx->pkfile, &pub_key_bytes,
+ &pub_key_size);
+ if (err)
+ return grub_error (err, N_("Failed to read public key file %s"),
+ ctx->pkfile);
+
+ err = grub_tpm2_protector_unmarshal_pkfile (pub_key_bytes,
+ pub_key_size,
+ &pub_key);
+ if (err)
+ {
+ grub_error (err, N_("Failed to unmarshal public key, ensure the public "
+ "key file is in TPM wire format"));
+ goto exit1;
+ }
+
+ /* Retrieve Signed PCR Policy */
+ err = grub_tpm2_protector_read_file (ctx->sigfile, &sig_bytes,
+ &sig_size);
+ if (err)
+ {
+ grub_error (err, N_("Failed to read signed pcr policy file %s"),
+ ctx->sigfile);
+ goto exit1;
+ }
+
+ err = grub_tpm2_protector_unmarshal_sigfile (sig_bytes,
+ sig_size,
+ &signature);
+ if (err)
+ {
+ grub_error (err, N_("Failed to unmarshal signed PCR policy, ensure the signed "
+ "PCR policy file is in TPM wire format"));
+ goto exit1;
+ }
+
+ /* Retrieve Sealed Key */
+ err = grub_tpm2_protector_read_file (ctx->keyfile, &sealed_key_bytes,
+ &sealed_key_size);
+ if (err)
+ {
+ grub_error (err, N_("Failed to read key file %s"), ctx->keyfile);
+ goto exit1;
+ }
+
+ err = grub_tpm2_protector_unmarshal_keyfile (sealed_key_bytes,
+ sealed_key_size,
+ &sealed_key);
+ if (err)
+ {
+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in "
+ "TPM wire format"));
+ goto exit1;
+ }
+
+ /* Reproduce the policy signed by the public key */
+ err = grub_tpm2_protector_authpol_digest (ctx, &pcr_policy);
+ if (err)
+ {
+ grub_error (err, N_("Failed to get the policy digest"));
+ goto exit1;
+ }
+
+ /* Load the public key */
+ rc = TPM2_LoadExternal (NULL, NULL, &pub_key, TPM_RH_OWNER,
+ &pubkey_handle, &pubname, NULL);
+ if (rc)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to load public key (TPM2_LoadExternal failed "
+ "with TSS/TPM error %u)"), rc);
+ goto exit1;
+ }
+
+ /* Calculate the digest of the polcy for VerifySignature */
+ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, TPM_ALG_SHA256,
+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL);
+ if (rc)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to create PCR policy hash (TPM2_Hash failed "
+ "with TSS/TPM error %u)"), rc);
+ goto exit2;
+ }
+
+ /* Verify the signature against the public key and the reproduced policy digest */
+ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature,
+ &verification_ticket, NULL);
+ if (rc)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to verify signature (TPM2_VerifySignature "
+ "failed with TSS/TPM error %u)"), rc);
+ goto exit2;
+ }
+
+ /* Get the handle of the primary storage key */
+ err = grub_tpm2_protector_srk_get (ctx, &primary_handle);
+ if (err)
+ {
+ grub_error (err, N_("Failed to create primary"));
+ goto exit2;
+ }
+
+ /* Load Sealed Key */
+ /* Use the password session with an empty password */
+ grub_memset (&authCmd, 0, sizeof (authCmd));
+ authCmd.sessionHandle = TPM_RS_PW;
+ /* Load the sealed object into TPM */
+ rc = TPM2_Load (primary_handle, &authCmd, &sealed_key.private, &sealed_key.public,
+ &sealed_key_handle, NULL, NULL);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to load sealed key (TPM2_Load failed with "
+ "TSS/TPM error %u)"), rc);
+ goto exit3;
+ }
+
+ /* Start a policy session to authorize the signed policy */
+ symmetric.algorithm = TPM_ALG_AES;
+ symmetric.keyBits.aes = 128;
+ symmetric.mode.aes = TPM_ALG_CFB;
+ nonceCaller.size = TPM_SHA256_DIGEST_SIZE;
+
+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonceCaller, NULL,
+ TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256,
+ &session, NULL, NULL);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession "
+ "failed with TSS/TPM error %u)"), rc);
+ goto exit4;
+ }
+
+ /* Send the PolicyPCR command to generate the policy digest based on the */
+ /* current PCR values */
+ rc = TPM2_PolicyPCR (session, NULL, NULL, &ctx->pcr_list, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ err = GRUB_ERR_BAD_DEVICE;
+ grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed "
+ "with TSS/TPM error: 0x%u).\n"), rc);
+ goto exit5;
+ }
+
+ /* Authorize the signed policy with the public key and the verification ticket */
+ rc = TPM2_PolicyAuthorize (session, NULL, &pcr_policy, NULL, &pubname,
+ &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);
+ goto exit5;
+ }
+
+ /* Unseal the key with the policy session that authorizes the signed policy */
+ grub_memset (&authCmd, 0, sizeof (authCmd));
+ authCmd.sessionHandle = session;
+ rc = TPM2_Unseal (sealed_key_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 failed"
+ "with TSS/TPM error: 0x%u).\n"), rc);
+ grub_millisleep(500);
+ goto exit5;
+ }
+
+ /* Epilogue */
+ key_out = grub_malloc (data.size);
+ if (!key_out)
+ {
+ err = GRUB_ERR_OUT_OF_MEMORY;
+ grub_error (err, N_("No memory left to allocate unlock key buffer"));
+ goto exit4;
+ }
+
+ grub_printf("TPM2: unsealed %u bytes of key material\n", data.size);
+
+ if (ctx->efivar)
+ {
+ rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar);
+ if (rc)
+ goto exit4;
+ }
+
+ grub_memcpy (key_out, data.buffer, data.size);
+
+ *key = key_out;
+ *key_size = data.size;
+
+ err = GRUB_ERR_NONE;
+
+exit5:
+ TPM2_FlushContext (session);
+
+exit4:
+ TPM2_FlushContext (sealed_key_handle);
+
+exit3:
+ TPM2_FlushContext (primary_handle);
+
+exit2:
+ TPM2_FlushContext (pubkey_handle);
+
+exit1:
+ grub_free (sealed_key_bytes);
+ grub_free (pub_key_bytes);
+ grub_free (sig_bytes);
+
+ return err;
+}
+
static grub_err_t
grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx,
grub_uint8_t **key, grub_size_t *key_size)
@@ -496,6 +1008,8 @@ grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx,
return grub_tpm2_protector_srk_recover (ctx, key, key_size);
case GRUB_TPM2_PROTECTOR_MODE_NV:
return grub_tpm2_protector_nv_recover (ctx, key, key_size);
+ case GRUB_TPM2_PROTECTOR_MODE_AUTHPOL:
+ return grub_tpm2_protector_authpol_recover (ctx, key, key_size);
default:
return GRUB_ERR_BAD_ARGUMENT;
}
@@ -543,7 +1057,10 @@ initialize_pcr_list (struct grub_tpm2_protector_context *ctx)
static grub_err_t
grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx)
{
- if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET)
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET && ctx->keyfile &&
+ ctx->pkfile && ctx->sigfile)
+ ctx->mode = GRUB_TPM2_PROTECTOR_MODE_AUTHPOL;
+ else if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET)
ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK;
/* Checks for SRK mode */
@@ -556,6 +1073,14 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("In SRK mode, an NV Index cannot be specified"));
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->pkfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In SRK mode, an a public key cannot be specified"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->sigfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In SRK mode, an a signed pcr policy cannot be specified"));
+
/* Checks for NV mode */
if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && !ctx->nv)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
@@ -575,6 +1100,34 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx)
N_("In NV Index mode, an asymmetric key type cannot be "
"specified"));
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->pkfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, an a public key cannot be specified"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->sigfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, an a signed pcr policy cannot be specified"));
+
+ /* Checks for Authorized Policy mode */
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->keyfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In Authorized Policy mode, a key file must be specified: "
+ "--keyfile or -k"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->pkfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In Authorized Policy mode, a public key file must be specified: "
+ "--pkfile or -P"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->sigfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In Authorized Policy mode, a signed pcr file must be specified: "
+ "--sigfile or -S"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && ctx->nv)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In Authorized Policy mode, an NV Index cannot be specified"));
+
/* Defaults assignment */
if (!ctx->bank)
ctx->bank = TPM_ALG_SHA256;
@@ -585,7 +1138,8 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx)
ctx->pcr_count = 1;
}
- if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK)
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK ||
+ ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL)
{
if (!ctx->srk)
ctx->srk = TPM2_SRK_HANDLE;
@@ -619,6 +1173,18 @@ grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile)
return grub_tpm2_protector_parse_string (value, keyfile, "keyfile");
}
+static grub_err_t
+grub_tpm2_protector_parse_pkfile (const char *value, const char **pkfile)
+{
+ return grub_tpm2_protector_parse_string (value, pkfile, "pkfile");
+}
+
+static grub_err_t
+grub_tpm2_protector_parse_sigfile (const char *value, const char **sigfile)
+{
+ return grub_tpm2_protector_parse_string (value, sigfile, "sigfile");
+}
+
static grub_err_t
grub_tpm2_protector_parse_efivar (const char *value, const char **efivar)
{
@@ -633,6 +1199,8 @@ grub_tpm2_protector_parse_mode (const char *value,
*mode = GRUB_TPM2_PROTECTOR_MODE_SRK;
else if (grub_strcmp (value, "nv") == 0)
*mode = GRUB_TPM2_PROTECTOR_MODE_NV;
+ else if (grub_strcmp (value, "authpol") == 0)
+ *mode = GRUB_TPM2_PROTECTOR_MODE_AUTHPOL;
else
return grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("Value '%s' is not a valid TPM2 key protector mode"),
@@ -722,6 +1290,22 @@ grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc,
return err;
}
+ if (state[8].set) /* pkfile */
+ {
+ err = grub_tpm2_protector_parse_pkfile (state[8].arg,
+ &grub_tpm2_protector_ctx.pkfile);
+ if (err)
+ return err;
+ }
+
+ if (state[9].set) /* sigfile */
+ {
+ err = grub_tpm2_protector_parse_sigfile (state[9].arg,
+ &grub_tpm2_protector_ctx.sigfile);
+ if (err)
+ return err;
+ }
+
err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx);
/* This command only initializes the protector, so nothing else to do. */
@@ -739,6 +1323,8 @@ grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__
N_("tpm2_key_protector_clear accepts no arguments"));
grub_free ((void *) grub_tpm2_protector_ctx.keyfile);
+ grub_free ((void *) grub_tpm2_protector_ctx.pkfile);
+ grub_free ((void *) grub_tpm2_protector_ctx.sigfile);
grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx));
return GRUB_ERR_NONE;
@@ -761,7 +1347,9 @@ GRUB_MOD_INIT (tpm2)
"[-k sealed_key_file_path] "
"[-s srk_handle] "
"[-a asymmetric_key_type] "
- "[-n nv_index]"),
+ "[-n nv_index] "
+ "[-P public_key_file_path] "
+ "[-S signature_file_path]"),
N_("Initialize the TPM2 key protector."),
grub_tpm2_protector_init_cmd_options);
grub_tpm2_protector_clear_cmd =
@@ -775,6 +1363,8 @@ GRUB_MOD_INIT (tpm2)
GRUB_MOD_FINI (tpm2)
{
grub_free ((void *) grub_tpm2_protector_ctx.keyfile);
+ grub_free ((void *) grub_tpm2_protector_ctx.pkfile);
+ grub_free ((void *) grub_tpm2_protector_ctx.sigfile);
grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx));
grub_key_protector_unregister (&grub_tpm2_key_protector);
--
2.35.3