Hi, folks. I have long wished that GRUB would give me a chance to retry whenever I make a typo in a LUKS passphrase, rather than immediately dumping me into the rescue shell, so I finally took a crack at it myself.
Would this be a welcome addition? The patch is a bit easier to read in a viewer that ignores whitespace, since a good chunk of the changed lines are from reordering and indenting existing code. Signed-off-by: Forest <fores...@nom.one> --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -1063,6 +1063,7 @@ grub_cryptodisk_dev_t cr; struct cryptodisk_read_hook_ctx read_hook_data = {0}; int askpass = 0; + int tries; char *part = NULL; dev = grub_cryptodisk_get_by_source_disk (source); @@ -1114,33 +1115,48 @@ if (!dev) continue; - if (!cargs->key_len) + if (cargs->key_len) + { + ret = cr->recover_key (source, dev, cargs); + if (ret != GRUB_ERR_NONE) + goto error; + } + else { /* 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)) + for (tries = GRUB_CRYPTODISK_PASSPHRASE_TRIES; tries > 0; tries--) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied"); - goto error; + 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); + + 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 = cr->recover_key (source, dev, cargs); + if (ret == GRUB_ERR_NONE) + break; + if (ret != GRUB_ERR_ACCESS_DENIED || tries == 1) + goto error; + grub_puts_ (N_("Invalid passphrase.")); + + /* Clear the last error to avoid recover_key() retry failure. */ + grub_errno = GRUB_ERR_NONE; } - cargs->key_len = grub_strlen ((char *) cargs->key_data); } - ret = cr->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; --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -64,6 +64,9 @@ #define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192 +/* Number of passphrase attempts the user is allowed. Must be > 0. */ +#define GRUB_CRYPTODISK_PASSPHRASE_TRIES 3 + struct grub_cryptodisk; typedef gcry_err_code_t _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel