Previously, NV index mode only supported persistent handles which are only for the TPM objects. Without introducing new parameters, it is difficult to support authorized policy.
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 stores 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|policywrite|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 | 72 ++++++++++++++++--- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c index e58da6f7a..1b3b89df8 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) @@ -1207,22 +1251,23 @@ tpm2_protector_check_args (tpm2_protector_context_t *ctx) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, please specify a key file with only --tpm2key/-T or --keyfile/-k")); if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && ctx->nv != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, an NV Index cannot be specified")); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, a NV Index cannot be specified")); /* Checks for NV mode */ if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->nv == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an NV Index must be specified: --nvindex or -n")); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, a NV Index must be specified: --nvindex or -n")); 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")); - 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_("in NV Index mode with a persistent handle, a SRK cannot be specified")); 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_("in NV Index mode, a NV index must be a persistent or NV index handle")); /* 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_NIS_P256 as the default SRK when using SRK mode or NV mode with + * a 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