Previously, NV index mode only supported persistent handles which are only for TPM objects.
On the other hand, the "NV index" handle allows the user-defined data, so it can be an alternative to the key file and support TPM 2.0 Key File format immediately. The following tpm2-tools commands store the given key file, sealed.tpm, in either TPM 2.0 Key File format or the raw format into the NV index handle 0x1000000. # tpm2_nvdefine -C o \ -a "ownerread|ownerwrite" \ -s $(stat -c %s sealed.tpm) \ 0x1000000 # tpm2_nvwrite -C o -i sealed.tpm 0x1000000 To unseal the key in GRUB, add the 'tpm2_key_protector_init' command to grub.cfg: tpm2_key_protector_init --mode=nv --nvindex=0x1000000 cryptomount -u <UUID> --protector tpm2 To remove the NV index handle: # tpm2_nvundefine -C o 0x1000000 Signed-off-by: Gary Lin <g...@suse.com> --- .../commands/tpm2_key_protector/module.c | 70 ++++++++++++++++--- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c index 8ec143542..56b44012c 100644 --- a/grub-core/commands/tpm2_key_protector/module.c +++ b/grub-core/commands/tpm2_key_protector/module.c @@ -1133,10 +1133,9 @@ tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx, } static grub_err_t -tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx, - grub_uint8_t **key, grub_size_t *key_size) +tpm2_protector_unseal_persistent (const tpm2_protector_context_t *ctx, TPM_HANDLE_t sealed_handle, + grub_uint8_t **key, grub_size_t *key_size) { - TPM_HANDLE_t sealed_handle = ctx->nv; tpm2key_policy_t policy_seq = NULL; bool dump_pcr = false; grub_err_t err; @@ -1163,6 +1162,51 @@ tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx, return err; } +static grub_err_t +tpm2_protector_unseal_nvindex (const tpm2_protector_context_t *ctx, TPM_HANDLE_t nvindex, + grub_uint8_t **key, grub_size_t *key_size) +{ + TPMS_AUTH_COMMAND_t authCmd = {0}; + TPM2B_NV_PUBLIC_t nv_public; + TPM2B_NAME_t nv_name; + grub_uint16_t data_size; + TPM2B_MAX_NV_BUFFER_t data; + TPM_RC_t rc; + + /* Get the data size in the NV index handle */ + rc = grub_tpm2_nv_readpublic (nvindex, NULL, &nv_public, &nv_name); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve info from 0x%x (TPM2_NV_ReadPublic: 0x%x)", nvindex, rc); + + data_size = nv_public.nvPublic.dataSize; + if (data_size > TPM_MAX_NV_BUFFER_SIZE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "insufficient data buffer"); + + /* Read the data from the NV index handle */ + authCmd.sessionHandle = TPM_RS_PW; + rc = grub_tpm2_nv_read (TPM_RH_OWNER, nvindex, &authCmd, data_size, 0, &data); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to read data from 0x%x (TPM2_NV_Read: 0x%x)", nvindex, rc); + + return tpm2_protector_unseal_buffer (ctx, data.buffer, data_size, key, key_size); +} + +static grub_err_t +tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx, + grub_uint8_t **key, grub_size_t *key_size) +{ + grub_err_t err; + + if (TPM_HT_IS_PERSISTENT (ctx->nv) == true) + err = tpm2_protector_unseal_persistent (ctx, ctx->nv, key, key_size); + else if (TPM_HT_IS_NVINDEX (ctx->nv) == true) + err = tpm2_protector_unseal_nvindex (ctx, ctx->nv, key, key_size); + else + err = GRUB_ERR_BAD_ARGUMENT; + + return err; +} + static grub_err_t tpm2_protector_recover (const tpm2_protector_context_t *ctx, grub_uint8_t **key, grub_size_t *key_size) @@ -1215,14 +1259,15 @@ tpm2_protector_check_args (tpm2_protector_context_t *ctx) if (ctx->mode == TPM2_PROTECTOR_MODE_NV && (ctx->tpm2key != NULL || ctx->keyfile != NULL)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, a keyfile cannot be specified")); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("a key file cannot be specified when using NV index mode")); - if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->srk != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an SRK cannot be specified")); + if (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_PERSISTENT (ctx->nv) == true && + (ctx->srk != 0 || ctx->srk_type.type != TPM_ALG_ERROR)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an SRK cannot be specified when using NV index mode with a persistent handle")); if (ctx->mode == TPM2_PROTECTOR_MODE_NV && - ctx->srk_type.type != TPM_ALG_ERROR) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an asymmetric key type cannot be specified")); + (TPM_HT_IS_PERSISTENT (ctx->nv) == false && TPM_HT_IS_NVINDEX (ctx->nv) == false)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an NV index must be either a persistent handle or an NV index handle when using NV index mode")); /* Defaults assignment */ if (ctx->bank == TPM_ALG_ERROR) @@ -1234,8 +1279,13 @@ tpm2_protector_check_args (tpm2_protector_context_t *ctx) ctx->pcr_count = 1; } - if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && - ctx->srk_type.type == TPM_ALG_ERROR) + /* + * Set ECC_NIST_P256 as the default SRK when using SRK mode or NV mode with + * an NV index handle + */ + if (ctx->srk_type.type == TPM_ALG_ERROR && + (ctx->mode == TPM2_PROTECTOR_MODE_SRK || + (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_NVINDEX (ctx->nv) == true))) { ctx->srk_type.type = TPM_ALG_ECC; ctx->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256; -- 2.43.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel