[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 04/14] cryptodisk: Support key protectors
From: |
Gary Lin |
Subject: |
Re: [PATCH 04/14] cryptodisk: Support key protectors |
Date: |
Thu, 23 Feb 2023 14:55:01 +0800 |
On Wed, Feb 22, 2023 at 03:00:44PM +0800, Gary Lin via Grub-devel wrote:
> From: Hernan Gatta <hegatta@linux.microsoft.com>
>
> Add a new parameter to cryptomount to support the key protectors framework:
> -k.
> The parameter is used to automatically retrieve a key from specified key
> protectors. The parameter may be repeated to specify any number of key
> protectors. These are tried in order until one provides a usable key for any
> given disk.
>
> Signed-off-by: <Hernan Gatta hegatta@linux.microsoft.com>
The email format is broken here and I didn't notice it...
Will fix the format in V2.
> Signed-off-by: Gary Lin <glin@suse.com>
> ---
> Makefile.util.def | 1 +
> grub-core/disk/cryptodisk.c | 175 +++++++++++++++++++++++++++++-------
> include/grub/cryptodisk.h | 14 +++
> 3 files changed, 157 insertions(+), 33 deletions(-)
>
> diff --git a/Makefile.util.def b/Makefile.util.def
> index beaef1168..1da5a826c 100644
> --- a/Makefile.util.def
> +++ b/Makefile.util.def
> @@ -35,6 +35,7 @@ library = {
> common = grub-core/kern/list.c;
> common = grub-core/kern/misc.c;
> common = grub-core/kern/partition.c;
> + common = grub-core/kern/protectors.c;
> common = grub-core/lib/crypto.c;
> common = grub-core/lib/json/json.c;
> common = grub-core/disk/luks.c;
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 34b67a705..c990d5985 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -26,6 +26,7 @@
> #include <grub/file.h>
> #include <grub/procfs.h>
> #include <grub/partition.h>
> +#include <grub/protector.h>
>
> #ifdef GRUB_UTIL
> #include <grub/emu/hostdisk.h>
> @@ -44,7 +45,8 @@ enum
> OPTION_KEYFILE,
> OPTION_KEYFILE_OFFSET,
> OPTION_KEYFILE_SIZE,
> - OPTION_HEADER
> + OPTION_HEADER,
> + OPTION_PROTECTOR
> };
>
> static const struct grub_arg_option options[] =
> @@ -58,6 +60,8 @@ static const struct grub_arg_option options[] =
> {"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0,
> ARG_TYPE_INT},
> {"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0,
> ARG_TYPE_INT},
> {"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
> + {"protector", 'k', GRUB_ARG_OPTION_REPEATABLE,
> + N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
> {0, 0, 0, 0, 0, 0}
> };
>
> @@ -1060,7 +1064,8 @@ grub_cryptodisk_scan_device_real (const char *name,
> {
> grub_err_t ret = GRUB_ERR_NONE;
> grub_cryptodisk_t dev;
> - grub_cryptodisk_dev_t cr;
> + grub_cryptodisk_dev_t cr, crd = NULL;
> + int i;
> struct cryptodisk_read_hook_ctx read_hook_data = {0};
> int askpass = 0;
> char *part = NULL;
> @@ -1113,41 +1118,112 @@ grub_cryptodisk_scan_device_real (const char *name,
> goto error_no_close;
> if (!dev)
> continue;
> + crd = cr;
> + }
>
> - if (!cargs->key_len)
> - {
> - /* Get the passphrase from the user, if no key data. */
> - askpass = 1;
> - part = grub_partition_get_name (source->partition);
> - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> - source->partition != NULL ? "," : "",
> - part != NULL ? part : N_("UNKNOWN"),
> - dev->uuid);
> - grub_free (part);
> -
> - cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
> - if (cargs->key_data == NULL)
> - goto error_no_close;
> -
> - if (!grub_password_get ((char *) cargs->key_data,
> GRUB_CRYPTODISK_MAX_PASSPHRASE))
> - {
> - grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
> - goto error;
> - }
> - cargs->key_len = grub_strlen ((char *) cargs->key_data);
> - }
> + if (!dev)
> + {
> + grub_error (GRUB_ERR_BAD_MODULE,
> + "no cryptodisk module can handle this device");
> + goto error_no_close;
> + }
>
> - ret = cr->recover_key (source, dev, cargs);
> - if (ret != GRUB_ERR_NONE)
> - goto error;
> + if (cargs->protectors)
> + {
> + for (i = 0; cargs->protectors[i]; i++)
> + {
> + if (cargs->key_cache[i].invalid)
> + continue;
> +
> + if (!cargs->key_cache[i].key)
> + {
> + ret = grub_key_protector_recover_key (cargs->protectors[i],
> + &cargs->key_cache[i].key,
> +
> &cargs->key_cache[i].key_len);
> + if (ret)
> + {
> + if (grub_errno)
> + {
> + grub_print_error ();
> + grub_errno = GRUB_ERR_NONE;
> + }
> +
> + grub_dprintf ("cryptodisk",
> + "failed to recover a key from key protector "
> + "%s, will not try it again for any other "
> + "disks, if any, during this invocation of "
> + "cryptomount\n",
> + cargs->protectors[i]);
> +
> + cargs->key_cache[i].invalid = 1;
> + continue;
> + }
> + }
> +
> + cargs->key_data = cargs->key_cache[i].key;
> + cargs->key_len = cargs->key_cache[i].key_len;
> +
> + ret = crd->recover_key (source, dev, cargs);
> + if (ret)
> + {
> + part = grub_partition_get_name (source->partition);
> + grub_dprintf ("cryptodisk",
> + "recovered a key from key protector %s but it "
> + "failed to unlock %s%s%s (%s)\n",
> + cargs->protectors[i], source->name,
> + source->partition != NULL ? "," : "",
> + part != NULL ? part : N_("UNKNOWN"), dev->uuid);
> + grub_free (part);
> + continue;
> + }
> + else
> + {
> + ret = grub_cryptodisk_insert (dev, name, source);
> + if (ret != GRUB_ERR_NONE)
> + goto error;
> + goto cleanup;
> + }
> + }
>
> - ret = grub_cryptodisk_insert (dev, name, source);
> - if (ret != GRUB_ERR_NONE)
> + part = grub_partition_get_name (source->partition);
> + grub_error (GRUB_ERR_ACCESS_DENIED,
> + N_("no key protector provided a usable key for %s%s%s
> (%s)"),
> + source->name, source->partition != NULL ? "," : "",
> + part != NULL ? part : N_("UNKNOWN"), dev->uuid);
> + grub_free (part);
> goto error;
> + }
> +
> + if (!cargs->key_len)
> + {
> + /* Get the passphrase from the user, if no key data. */
> + askpass = 1;
> + part = grub_partition_get_name (source->partition);
> + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> + source->partition != NULL ? "," : "",
> + part != NULL ? part : N_("UNKNOWN"), dev->uuid);
> + grub_free (part);
> +
> + cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
> + if (cargs->key_data == NULL)
> + goto error;
> +
> + if (!grub_password_get ((char *) cargs->key_data,
> GRUB_CRYPTODISK_MAX_PASSPHRASE))
> + {
> + grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
> + goto error;
> + }
> + cargs->key_len = grub_strlen ((char *) cargs->key_data);
> + }
> +
> + ret = crd->recover_key (source, dev, cargs);
> + if (ret != GRUB_ERR_NONE)
> + goto error;
> +
> + ret = grub_cryptodisk_insert (dev, name, source);
> + if (ret != GRUB_ERR_NONE)
> + goto error;
>
> - goto cleanup;
> - }
> - grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this
> device");
> goto cleanup;
>
> error:
> @@ -1258,6 +1334,20 @@ grub_cryptodisk_scan_device (const char *name,
> return ret;
> }
>
> +static void
> +grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
> +{
> + int i;
> +
> + if (!cargs->key_cache)
> + return;
> +
> + for (i = 0; cargs->protectors[i]; i++)
> + grub_free (cargs->key_cache[i].key);
> +
> + grub_free (cargs->key_cache);
> +}
> +
> static grub_err_t
> grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
> {
> @@ -1270,6 +1360,10 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> if (grub_cryptodisk_list == NULL)
> return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
>
> + if (state[OPTION_PASSWORD].set && state[OPTION_PROTECTOR].set) /* password
> and key protector */
> + return grub_error (GRUB_ERR_BAD_ARGUMENT,
> + "a password and a key protector cannot both be set");
> +
> if (state[OPTION_PASSWORD].set) /* password */
> {
> cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
> @@ -1362,6 +1456,15 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> return grub_errno;
> }
>
> + if (state[OPTION_PROTECTOR].set) /* key protector(s) */
> + {
> + cargs.key_cache = grub_zalloc (state[OPTION_PROTECTOR].set * sizeof
> (*cargs.key_cache));
> + if (!cargs.key_cache)
> + return grub_error (GRUB_ERR_OUT_OF_MEMORY,
> + "no memory for key protector key cache");
> + cargs.protectors = state[OPTION_PROTECTOR].args;
> + }
> +
> if (state[OPTION_UUID].set) /* uuid */
> {
> int found_uuid;
> @@ -1370,6 +1473,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> dev = grub_cryptodisk_get_by_uuid (args[0]);
> if (dev)
> {
> + grub_cryptodisk_clear_key_cache (&cargs);
> grub_dprintf ("cryptodisk",
> "already mounted as crypto%lu\n", dev->id);
> return GRUB_ERR_NONE;
> @@ -1378,6 +1482,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> cargs.check_boot = state[OPTION_BOOT].set;
> cargs.search_uuid = args[0];
> found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device,
> &cargs);
> + grub_cryptodisk_clear_key_cache (&cargs);
>
> if (found_uuid)
> return GRUB_ERR_NONE;
> @@ -1397,6 +1502,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> {
> cargs.check_boot = state[OPTION_BOOT].set;
> grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
> + grub_cryptodisk_clear_key_cache (&cargs);
> return GRUB_ERR_NONE;
> }
> else
> @@ -1420,6 +1526,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> disk = grub_disk_open (diskname);
> if (!disk)
> {
> + grub_cryptodisk_clear_key_cache (&cargs);
> if (disklast)
> *disklast = ')';
> return grub_errno;
> @@ -1430,12 +1537,14 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int
> argc, char **args)
> {
> grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n",
> dev->id);
> grub_disk_close (disk);
> + grub_cryptodisk_clear_key_cache (&cargs);
> if (disklast)
> *disklast = ')';
> return GRUB_ERR_NONE;
> }
>
> dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
> + grub_cryptodisk_clear_key_cache (&cargs);
>
> grub_disk_close (disk);
> if (disklast)
> @@ -1576,7 +1685,7 @@ GRUB_MOD_INIT (cryptodisk)
> cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
> N_("[ [-p password] | [-k keyfile"
> " [-O keyoffset] [-S keysize] ] ] [-H file]"
> - " <SOURCE|-u UUID|-a|-b>"),
> + " [-k protector [-k protector ...]] <SOURCE|-u
> UUID|-a|-b>"),
> N_("Mount a crypto device."), options);
> grub_procfs_register ("luks_script", &luks_script);
> }
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index d94df68b6..ce18df883 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -70,6 +70,16 @@ typedef gcry_err_code_t
> (*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
> grub_uint64_t zoneno);
>
> +struct grub_cryptomount_cached_key
> +{
> + grub_uint8_t *key;
> + grub_size_t key_len;
> +
> + /* The key protector associated with this cache entry failed, so avoid it
> + * even if the cached entry (an instance of this structure) is empty. */
> + int invalid;
> +};
> +
> struct grub_cryptomount_args
> {
> /* scan: Flag to indicate that only bootable volumes should be decrypted */
> @@ -81,6 +91,10 @@ struct grub_cryptomount_args
> /* recover_key: Length of key_data */
> grub_size_t key_len;
> grub_file_t hdr_file;
> + /* recover_key: Names of the key protectors to use (NULL-terminated) */
> + char **protectors;
> + /* recover_key: Key cache to avoid invoking the same key protector twice */
> + struct grub_cryptomount_cached_key *key_cache;
> };
> typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
>
> --
> 2.35.3
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
- [PATCH 02/14] tpm2: Add TPM Software Stack (TSS), (continued)
- [PATCH 02/14] tpm2: Add TPM Software Stack (TSS), Gary Lin, 2023/02/22
- [PATCH 03/14] protectors: Add TPM2 Key Protector, Gary Lin, 2023/02/22
- [PATCH 05/14] util/grub-protect: Add new tool, Gary Lin, 2023/02/22
- [PATCH 07/14] tpm2: Don't measure the sealed key, Gary Lin, 2023/02/22
- [PATCH 09/14] tpm2: declare the input arguments of TPM2 functions as const, Gary Lin, 2023/02/22
- [PATCH 13/14] tpm2: allow some command parameters to be NULL, Gary Lin, 2023/02/22
- [PATCH 14/14] tpm2: remove the unnecessary variables, Gary Lin, 2023/02/22
- [PATCH 04/14] cryptodisk: Support key protectors, Gary Lin, 2023/02/22
- Re: [PATCH 04/14] cryptodisk: Support key protectors,
Gary Lin <=
- [PATCH 06/14] crytodisk: fix cryptodisk module looking up, Gary Lin, 2023/02/22
- [PATCH 08/14] tpm2: adjust the input parameters of TPM2_EvictControl, Gary Lin, 2023/02/22
- [PATCH 11/14] tpm2: check the command parameters of TPM2 commands, Gary Lin, 2023/02/22
- [PATCH 10/14] tpm2: resend the command on TPM_RC_RETRY, Gary Lin, 2023/02/22
- [PATCH 12/14] tpm2: pack the missing authorization command for TPM2_PCR_Read, Gary Lin, 2023/02/22
- Re: [PATCH 00/14] Automatic Disk Unlock with TPM2, Daniel Kiper, 2023/02/28