All of lore.kernel.org
 help / color / mirror / Atom feed
From: Forest <forestix@nom.one>
To: The development of GNU GRUB <grub-devel@gnu.org>
Cc: Glenn Washburn <development@efficientek.com>,
	Daniel Kiper <daniel.kiper@oracle.com>
Subject: Re: [PATCH v3] cryptodisk: allow user to retry failed passphrase
Date: Sat, 27 Apr 2024 17:31:31 -0700	[thread overview]
Message-ID: <a06r2jlf447lr1mrso183a7k95d2rcmg5r@sonic.net> (raw)
In-Reply-To: <gv4r2j5tm592ipq03ccn2ir1aqd9622qkh@sonic.net>

Please ignore this rev in favor of v4, coming soon.

(I want to simplify the stale-errno guard around grub_strtoul().)


On Sat, 27 Apr 2024 17:15:42 -0700, Forest wrote:

>Give the user a chance to re-enter their cryptodisk passphrase after a typo,
>rather than immediately failing (and likely dumping them into a grub shell).
>
>By default, we allow 3 tries before giving up. A value in the
>cryptodisk_passphrase_tries environment variable will override this default.
>
>The user can give up early by entering an empty passphrase, just as they
>could before this patch.
>
>Signed-off-by: Forest <forestix@nom.one>
>---
> docs/grub.texi              |  9 +++++
> grub-core/disk/cryptodisk.c | 74 +++++++++++++++++++++++++++++--------
> 2 files changed, 67 insertions(+), 16 deletions(-)
>
>diff --git a/docs/grub.texi b/docs/grub.texi
>index a225f9a88..6ac603a32 100644
>--- a/docs/grub.texi
>+++ b/docs/grub.texi
>@@ -3277,6 +3277,7 @@ These variables have special meaning to GRUB.
> * color_normal::
> * config_directory::
> * config_file::
>+* cryptodisk_passphrase_tries::
> * debug::
> * default::
> * fallback::
>@@ -3441,6 +3442,14 @@ processed by commands @command{configfile} (@pxref{configfile}) or @command{norm
> (@pxref{normal}).  It is restored to the previous value when command completes.
> 
> 
>+@node cryptodisk_passphrase_tries
>+@subsection cryptodisk_passphrase_tries
>+
>+When prompting the user for a cryptodisk passphrase, allow this many attempts
>+before giving up. The default is @samp{3}. (The user can give up early by
>+entering an empty passphrase.)
>+
>+
> @node debug
> @subsection debug
> 
>diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
>index 2246af51b..4fa7dc58d 100644
>--- a/grub-core/disk/cryptodisk.c
>+++ b/grub-core/disk/cryptodisk.c
>@@ -17,6 +17,7 @@
>  */
> 
> #include <grub/cryptodisk.h>
>+#include <grub/env.h>
> #include <grub/mm.h>
> #include <grub/misc.h>
> #include <grub/dl.h>
>@@ -1063,6 +1064,8 @@ grub_cryptodisk_scan_device_real (const char *name,
>   grub_cryptodisk_dev_t cr;
>   struct cryptodisk_read_hook_ctx read_hook_data = {0};
>   int askpass = 0;
>+  unsigned long tries = 3;
>+  const char *tries_env;
>   char *part = NULL;
> 
>   dev = grub_cryptodisk_get_by_source_disk (source);
>@@ -1114,32 +1117,71 @@ grub_cryptodisk_scan_device_real (const char *name,
>     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))
>+	tries_env = grub_env_get ("cryptodisk_passphrase_tries");
>+	if (tries_env != NULL && tries_env[0] != '\0')
> 	  {
>-	    grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
>-	    goto error;
>+	    const char *p = NULL;
>+	    tries = grub_strtoul (tries_env, &p, 0);
>+	    if (*p != '\0')
>+	      {
>+		/* Account for grub_strtoul() ignoring trailing text. */
>+		grub_err_t err = grub_errno;
>+		if (p > tries_env && tries != ~0UL)
>+		  err = GRUB_ERR_BAD_NUMBER;
>+
>+		grub_error (err,
>+			    N_("non-numeric or invalid value for cryptodisk_passphrase_tries: `%s'"),
>+			    tries_env);
>+		goto error;
>+	      }
> 	  }
>-	cargs->key_len = grub_strlen ((char *) cargs->key_data);
>-      }
> 
>-    ret = cr->recover_key (source, dev, cargs);
>-    if (ret != GRUB_ERR_NONE)
>-      goto error;
>+	for (; tries > 0; tries--)
>+	  {
>+	    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."));
>+
>+	    /*
>+	     * Since recover_key() calls a function that returns grub_errno,
>+	     * a leftover error value from a previously rejected passphrase
>+	     * will trigger a phantom failure. We therefore clear it before
>+	     * trying a new passphrase.
>+	     */
>+	    grub_errno = GRUB_ERR_NONE;
>+	  }
>+      }
> 
>     ret = grub_cryptodisk_insert (dev, name, source);
>     if (ret != GRUB_ERR_NONE)

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

      reply	other threads:[~2024-04-28  0:32 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-28  0:15 [PATCH v3] cryptodisk: allow user to retry failed passphrase Forest
2024-04-28  0:31 ` Forest [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a06r2jlf447lr1mrso183a7k95d2rcmg5r@sonic.net \
    --to=forestix@nom.one \
    --cc=daniel.kiper@oracle.com \
    --cc=development@efficientek.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.