Re: [PATCH v11 12/20] cryptodisk: Support key protectors
On 4/12/24 04:39, Gary Lin via Grub-devel wrote: From: Hernan Gatta Add a new parameter to cryptomount to support the key protectors framework: -P. 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 Signed-off-by: Michael Chang Signed-off-by: Gary Lin Reviewed-by: Glenn Washburn --- Makefile.util.def | 1 + grub-core/disk/cryptodisk.c | 172 +--- include/grub/cryptodisk.h | 16 3 files changed, 158 insertions(+), 31 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index b53afb1d3..19ad5a96f 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -40,6 +40,7 @@ library = { common = grub-core/disk/luks.c; common = grub-core/disk/luks2.c; common = grub-core/disk/geli.c; + common = grub-core/disk/key_protector.c; common = grub-core/disk/cryptodisk.c; common = grub-core/disk/AFSplitter.c; common = grub-core/lib/pbkdf2.c; diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 2246af51b..0ca1a5c4d 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -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", 'P', GRUB_ARG_OPTION_REPEATABLE, + N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -1061,6 +1065,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_err_t ret = GRUB_ERR_NONE; grub_cryptodisk_t dev; grub_cryptodisk_dev_t cr; + 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; +break; + } -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 == NULL) +{ + 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 == NULL) + { + ret = grub_key_protector_recover_key (cargs->protectors[i], + >key_cache[i].key, + >key_cache[i].key_len); + if (ret != GRUB_ERR_NONE) + { + 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 =
[PATCH v11 12/20] cryptodisk: Support key protectors
From: Hernan Gatta Add a new parameter to cryptomount to support the key protectors framework: -P. 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 Signed-off-by: Michael Chang Signed-off-by: Gary Lin Reviewed-by: Glenn Washburn --- Makefile.util.def | 1 + grub-core/disk/cryptodisk.c | 172 +--- include/grub/cryptodisk.h | 16 3 files changed, 158 insertions(+), 31 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index b53afb1d3..19ad5a96f 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -40,6 +40,7 @@ library = { common = grub-core/disk/luks.c; common = grub-core/disk/luks2.c; common = grub-core/disk/geli.c; + common = grub-core/disk/key_protector.c; common = grub-core/disk/cryptodisk.c; common = grub-core/disk/AFSplitter.c; common = grub-core/lib/pbkdf2.c; diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 2246af51b..0ca1a5c4d 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -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", 'P', GRUB_ARG_OPTION_REPEATABLE, + N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -1061,6 +1065,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_err_t ret = GRUB_ERR_NONE; grub_cryptodisk_t dev; grub_cryptodisk_dev_t cr; + 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; +break; + } -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 == NULL) +{ + 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 == NULL) + { + ret = grub_key_protector_recover_key (cargs->protectors[i], + >key_cache[i].key, + >key_cache[i].key_len); + if (ret != GRUB_ERR_NONE) + { + 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 = grub_cryptodisk_insert (dev, name, source); -if (ret != GRUB_ERR_NONE) + ret = cr->recover_key (source,