* enable cryptomount to read passphrase from file
@ 2015-01-18 3:29 Alexandre Oliva
2015-01-18 14:57 ` Andrei Borzenkov
0 siblings, 1 reply; 3+ messages in thread
From: Alexandre Oliva @ 2015-01-18 3:29 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 723 bytes --]
Here's a compile-tested patch that attempts to add '-p FILE' support to
cryptomount, so that the passphrase can be read from a usb key or
somesuch.
I was unsure about how much to massage or verify the file, say, dropping
a trailing newline or truncating the passphrase at the first newline or
whatever. I ended up deciding to keep it simple and just use the file
contents unchanged in any way (though the passphrase users will use it
as a C string, so any NUL in the file will effectively truncate the
passphrase). Thoughts?
I've only checked that it builds, but I haven't really tested it yet
I'm not sure yet how to go about that without risking rendering my
boxes unbootable :-) Suggestions are welcome.
Thanks,
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: grub-cryptomount-passphrase-from-file.patch --]
[-- Type: text/x-patch, Size: 11949 bytes --]
Index: ChangeLog
from Alexandre Oliva <oliva@gnu.org>
* docs/grub.texi (cryptomount): Add -p file.
* grub-core/disk/cryptodisk.c (options): Likewise.
(grub_cryptodisk_scan_device_real): Add key parameter. Pass it to
recover_key.
(grub_cryptodisk_scan_device): Likewise.
(grub_cmd_cryptomount): Read key from file. Pass it on.
(GRUB_MOD_INIT): Adjust cryptomount usage.
* include/grub/cryptodisk.h (GRUB_CRYPTODISK_MAX_PASSPHRASE): New.
(grub_cyrptodisk_dev::recover_key): Add key parameter.
* grub-core/disk/geli.c (MAX_PASSPHRASE): Define to
GRUB_CRYPTODISK_MAX_PASSPHRASE.
(recover_key): Add key parameter; try it first if given, retry
with keyboard-read passphrase.
* grub-core/disk/luks.c (MAX_PASSPHRASE, luks_recover_key):
Likewise.
Index: docs/grub.texi
--- grub.orig/docs/grub.texi 2014-10-14 23:30:59.000000000 -0300
+++ grub/docs/grub.texi 2015-01-18 01:26:49.499924206 -0200
@@ -4073,9 +4073,12 @@ Alias for @code{hashsum --hash crc32 arg
@node cryptomount
@subsection cryptomount
-@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
-Setup access to encrypted device. If necessary, passphrase
-is requested interactively. Option @var{device} configures specific grub device
+@deffn Command cryptomount [@option{-p} file] device|@option{-u} uuid|@option{-a}|@option{-b}
+Setup access to encrypted device. The passphrase will be asked
+interactively, unless @option{-p} @var{file} is specified and the
+passphrase read from the file succeeds. The file should contain
+@emph{only} the passphrase, not even a trailing line break. Option
+@var{device} configures specific grub device
(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
with specified @var{uuid}; option @option{-a} configures all detected encrypted
devices; option @option{-b} configures all geli containers that have boot flag set.
Index: grub-core/disk/cryptodisk.c
--- grub.orig/grub-core/disk/cryptodisk.c 2014-10-14 23:30:57.000000000 -0300
+++ grub/grub-core/disk/cryptodisk.c 2015-01-18 01:08:27.506796052 -0200
@@ -40,6 +40,8 @@ static const struct grub_arg_option opti
/* TRANSLATORS: It's still restricted to cryptodisks only. */
{"all", 'a', 0, N_("Mount all."), 0, 0},
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
+ {"passfile", 'p', 0, N_("Read the passphrase from the named file."),
+ N_("FILE"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -806,7 +808,8 @@ cryptodisk_close (grub_cryptodisk_t dev)
}
static grub_err_t
-grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
+grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source,
+ const char *key)
{
grub_err_t err;
grub_cryptodisk_t dev;
@@ -825,7 +828,7 @@ grub_cryptodisk_scan_device_real (const
if (!dev)
continue;
- err = cr->recover_key (source, dev);
+ err = cr->recover_key (source, dev, key);
if (err)
{
cryptodisk_close (dev);
@@ -890,10 +893,11 @@ grub_cryptodisk_cheat_mount (const char
static int
grub_cryptodisk_scan_device (const char *name,
- void *data __attribute__ ((unused)))
+ void *data)
{
grub_err_t err;
grub_disk_t source;
+ const char *key = data;
/* Try to open disk. */
source = grub_disk_open (name);
@@ -903,7 +907,7 @@ grub_cryptodisk_scan_device (const char
return 0;
}
- err = grub_cryptodisk_scan_device_real (name, source);
+ err = grub_cryptodisk_scan_device_real (name, source, key);
grub_disk_close (source);
@@ -916,10 +920,49 @@ static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
+ char *key = NULL;
+ char buf[GRUB_CRYPTODISK_MAX_PASSPHRASE];
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+ /* Read key from file. */
+ if (ctxt->state[3].set)
+ {
+ char *fname = ctxt->state[3].arg;
+ grub_file_t file;
+ file = grub_file_open (fname);
+ if (!file)
+ grub_printf_ (N_("Failed to open passphrase file\n"));
+ else if (file)
+ {
+ grub_ssize_t size;
+ size = grub_file_read (file, buf, sizeof (buf));
+ if (size < 0)
+ grub_printf_ (N_("Error reading from passphrase file\n"));
+ else if (size == 0)
+ grub_printf_ (N_("Passphrase file is empty\n"));
+ else if ((grub_size_t)size >= sizeof (buf))
+ grub_printf_ (N_("Passphrase file is too big\n"));
+ else
+ {
+#if 0
+ int count;
+ for (count = 0; count < size; count++)
+ if (buf[count] == 0
+ || buf[count] == '\n'
+ || buf[count] == '\r')
+ break;
+ if (count != size)
+ grub_printf_ (N_("Extraneous byte in passphrase file!\n"));
+#endif
+ grub_memset (buf + size, 0, sizeof (buf) - size);
+ key = buf;
+ }
+ }
+ grub_file_close (file);
+ }
+
have_it = 0;
if (state[0].set)
{
@@ -935,7 +978,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
check_boot = state[2].set;
search_uuid = args[0];
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ grub_device_iterate (&grub_cryptodisk_scan_device, key);
search_uuid = NULL;
if (!have_it)
@@ -946,7 +989,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
{
search_uuid = NULL;
check_boot = state[2].set;
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ grub_device_iterate (&grub_cryptodisk_scan_device, key);
search_uuid = NULL;
return GRUB_ERR_NONE;
}
@@ -980,7 +1023,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
return GRUB_ERR_NONE;
}
- err = grub_cryptodisk_scan_device_real (args[0], disk);
+ err = grub_cryptodisk_scan_device_real (args[0], disk, key);
grub_disk_close (disk);
@@ -1117,7 +1160,7 @@ GRUB_MOD_INIT (cryptodisk)
{
grub_disk_dev_register (&grub_cryptodisk_dev);
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
- N_("SOURCE|-u UUID|-a|-b"),
+ N_("[-p FILE] SOURCE|-u UUID|-a|-b"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
}
Index: include/grub/cryptodisk.h
--- grub.orig/include/grub/cryptodisk.h 2014-10-14 23:31:00.000000000 -0300
+++ grub/include/grub/cryptodisk.h 2015-01-18 00:14:22.572709178 -0200
@@ -54,6 +54,10 @@ typedef enum
#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
+/* Backends may limit passphrases to smaller sizes, but this should be
+ the max among them all. */
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
+
struct grub_cryptodisk;
typedef gcry_err_code_t
@@ -107,7 +111,8 @@ struct grub_cryptodisk_dev
grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
int boot_only);
- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev,
+ const char *key);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
Index: grub-core/disk/geli.c
--- grub.orig/grub-core/disk/geli.c 2014-10-14 23:30:57.000000000 -0300
+++ grub/grub-core/disk/geli.c 2015-01-18 01:06:31.422050391 -0200
@@ -135,7 +135,7 @@ const char *algorithms[] = {
[0x16] = "aes"
};
-#define MAX_PASSPHRASE 256
+#define MAX_PASSPHRASE GRUB_CRYPTODISK_MAX_PASSPHRASE
static gcry_err_code_t
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
@@ -384,7 +384,7 @@ configure_ciphers (grub_disk_t disk, con
}
static grub_err_t
-recover_key (grub_disk_t source, grub_cryptodisk_t dev)
+recover_key (grub_disk_t source, grub_cryptodisk_t dev, const char *key)
{
grub_size_t keysize;
grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@@ -419,16 +419,31 @@ recover_key (grub_disk_t source, grub_cr
grub_puts_ (N_("Attempting to decrypt master key..."));
- /* Get the passphrase from the user. */
+ retry:
tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+ if (key && grub_strlen (key) >= MAX_PASSPHRASE)
+ {
+ grub_printf_ (N_("Discarding too-long supplied passphrase\n"));
+ key = NULL;
+ }
+ if (key)
+ {
+ grub_size_t len = grub_strlen (key);
+ grub_memcpy (passphrase, key, len);
+ grub_memset (passphrase + len, 0, sizeof (passphrase) - len);
+ }
+ else
+ {
+ /* Get the passphrase from the user. */
+ if (source->partition)
+ tmp = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition ? "," : "", tmp ? : "",
+ dev->uuid);
+ grub_free (tmp);
+ if (!grub_password_get (passphrase, MAX_PASSPHRASE))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+ }
/* Calculate the PBKDF2 of the user supplied passphrase. */
if (grub_le_to_cpu32 (header.niter) != 0)
@@ -548,6 +563,13 @@ recover_key (grub_disk_t source, grub_cr
return GRUB_ERR_NONE;
}
+ if (key)
+ {
+ grub_printf_ (N_("Supplied passphrase failed to unlock key\n"));
+ key = NULL;
+ goto retry;
+ }
+
return GRUB_ACCESS_DENIED;
}
Index: grub-core/disk/luks.c
--- grub.orig/grub-core/disk/luks.c 2014-10-14 23:30:57.000000000 -0300
+++ grub/grub-core/disk/luks.c 2015-01-18 01:06:26.336192968 -0200
@@ -29,7 +29,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
-#define MAX_PASSPHRASE 256
+#define MAX_PASSPHRASE GRUB_CRYPTODISK_MAX_PASSPHRASE
#define LUKS_KEY_ENABLED 0x00AC71F3
@@ -297,7 +297,8 @@ configure_ciphers (grub_disk_t disk, con
static grub_err_t
luks_recover_key (grub_disk_t source,
- grub_cryptodisk_t dev)
+ grub_cryptodisk_t dev,
+ const char *key)
{
struct grub_luks_phdr header;
grub_size_t keysize;
@@ -328,18 +329,33 @@ luks_recover_key (grub_disk_t source,
if (!split_key)
return grub_errno;
- /* Get the passphrase from the user. */
+ retry:
tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
+ if (key && grub_strlen (key) >= MAX_PASSPHRASE)
{
- grub_free (split_key);
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+ grub_printf_ (N_("Discarding too-long supplied passphrase\n"));
+ key = NULL;
+ }
+ if (key)
+ {
+ grub_size_t len = grub_strlen (key);
+ grub_memcpy (passphrase, key, len);
+ grub_memset (passphrase + len, 0, sizeof (passphrase) - len);
+ }
+ else
+ {
+ /* Get the passphrase from the user. */
+ if (source->partition)
+ tmp = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition ? "," : "", tmp ? : "",
+ dev->uuid);
+ grub_free (tmp);
+ if (!grub_password_get (passphrase, MAX_PASSPHRASE))
+ {
+ grub_free (split_key);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+ }
}
/* Try to recover master key from each active keyslot. */
@@ -451,6 +467,13 @@ luks_recover_key (grub_disk_t source,
return GRUB_ERR_NONE;
}
+ if (key)
+ {
+ grub_printf_ (N_("Supplied passphrase failed to unlock key\n"));
+ key = NULL;
+ goto retry;
+ }
+
return GRUB_ACCESS_DENIED;
}
[-- Attachment #3: Type: text/plain, Size: 257 bytes --]
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: enable cryptomount to read passphrase from file
2015-01-18 3:29 enable cryptomount to read passphrase from file Alexandre Oliva
@ 2015-01-18 14:57 ` Andrei Borzenkov
2015-01-19 6:33 ` Alexandre Oliva
0 siblings, 1 reply; 3+ messages in thread
From: Andrei Borzenkov @ 2015-01-18 14:57 UTC (permalink / raw)
To: Alexandre Oliva; +Cc: grub-devel, John Lane
В Sun, 18 Jan 2015 01:29:45 -0200
Alexandre Oliva <oliva@gnu.org> пишет:
> Here's a compile-tested patch that attempts to add '-p FILE' support to
> cryptomount, so that the passphrase can be read from a usb key or
> somesuch.
>
I suggest you cooperate with John for this; he has a set of patches to
support it as well. See also http://grub.johnlane.ie/.
> I was unsure about how much to massage or verify the file, say, dropping
> a trailing newline or truncating the passphrase at the first newline or
> whatever. I ended up deciding to keep it simple and just use the file
> contents unchanged in any way (though the passphrase users will use it
> as a C string, so any NUL in the file will effectively truncate the
> passphrase). Thoughts?
>
Just pass in passphrase+len. Do not expect anything about content of
passphrase file at all.
>
> I've only checked that it builds, but I haven't really tested it yet
> I'm not sure yet how to go about that without risking rendering my
> boxes unbootable :-) Suggestions are welcome.
>
You can always unlock encrypted filesystem manually, right?
> Thanks,
>
> Index: docs/grub.texi
> --- grub.orig/docs/grub.texi 2014-10-14 23:30:59.000000000 -0300
> +++ grub/docs/grub.texi 2015-01-18 01:26:49.499924206 -0200
> @@ -4073,9 +4073,12 @@ Alias for @code{hashsum --hash crc32 arg
> @node cryptomount
> @subsection cryptomount
>
> -@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
> -Setup access to encrypted device. If necessary, passphrase
> -is requested interactively. Option @var{device} configures specific grub device
> +@deffn Command cryptomount [@option{-p} file] device|@option{-u} uuid|@option{-a}|@option{-b}
> +Setup access to encrypted device. The passphrase will be asked
> +interactively, unless @option{-p} @var{file} is specified and the
> +passphrase read from the file succeeds. The file should contain
> +@emph{only} the passphrase, not even a trailing line break. Option
> +@var{device} configures specific grub device
Hmm ... I'm not sure whether we should fallback to asking user. The whole
point of using keyfile is to avoid user interaction in the first place,
right? May be it makes more sense to simply fail boot in this case?
This allows you to continue with nexct boot option.
> (@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
> with specified @var{uuid}; option @option{-a} configures all detected encrypted
> devices; option @option{-b} configures all geli containers that have boot flag set.
> Index: grub-core/disk/cryptodisk.c
> --- grub.orig/grub-core/disk/cryptodisk.c 2014-10-14 23:30:57.000000000 -0300
> +++ grub/grub-core/disk/cryptodisk.c 2015-01-18 01:08:27.506796052 -0200
>
> @@ -916,10 +920,49 @@ static grub_err_t
> grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
> {
> struct grub_arg_list *state = ctxt->state;
> + char *key = NULL;
> + char buf[GRUB_CRYPTODISK_MAX_PASSPHRASE];
>
> if (argc < 1 && !state[1].set && !state[2].set)
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
>
> + /* Read key from file. */
> + if (ctxt->state[3].set)
> + {
> + char *fname = ctxt->state[3].arg;
> + grub_file_t file;
> + file = grub_file_open (fname);
> + if (!file)
> + grub_printf_ (N_("Failed to open passphrase file\n"));
> + else if (file)
Comparison is redundant; it was already checked to be !NULL.
> + {
> + grub_ssize_t size;
> + size = grub_file_read (file, buf, sizeof (buf));
> + if (size < 0)
> + grub_printf_ (N_("Error reading from passphrase file\n"));
> + else if (size == 0)
> + grub_printf_ (N_("Passphrase file is empty\n"));
> + else if ((grub_size_t)size >= sizeof (buf))
Can it be larger than sizeof(buf)?
> + grub_printf_ (N_("Passphrase file is too big\n"));
With my non-native English I find "too long" sounds better.
> + else
> + {
> +#if 0
> + int count;
> + for (count = 0; count < size; count++)
> + if (buf[count] == 0
> + || buf[count] == '\n'
> + || buf[count] == '\r')
> + break;
> + if (count != size)
> + grub_printf_ (N_("Extraneous byte in passphrase file!\n"));
> +#endif
Is it prohibited to have new line or carriage return in passphrase file?
> + grub_memset (buf + size, 0, sizeof (buf) - size);
> + key = buf;
> + }
> + }
> + grub_file_close (file);
> + }
> +
> have_it = 0;
> if (state[0].set)
> {
> @@ -935,7 +978,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
>
> check_boot = state[2].set;
> search_uuid = args[0];
> - grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
> + grub_device_iterate (&grub_cryptodisk_scan_device, key);
> search_uuid = NULL;
>
> if (!have_it)
> @@ -946,7 +989,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
> {
> search_uuid = NULL;
> check_boot = state[2].set;
> - grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
> + grub_device_iterate (&grub_cryptodisk_scan_device, key);
> search_uuid = NULL;
> return GRUB_ERR_NONE;
> }
> @@ -980,7 +1023,7 @@ grub_cmd_cryptomount (grub_extcmd_contex
> return GRUB_ERR_NONE;
> }
>
> - err = grub_cryptodisk_scan_device_real (args[0], disk);
> + err = grub_cryptodisk_scan_device_real (args[0], disk, key);
>
> grub_disk_close (disk);
>
> @@ -1117,7 +1160,7 @@ GRUB_MOD_INIT (cryptodisk)
> {
> grub_disk_dev_register (&grub_cryptodisk_dev);
> cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
> - N_("SOURCE|-u UUID|-a|-b"),
> + N_("[-p FILE] SOURCE|-u UUID|-a|-b"),
> N_("Mount a crypto device."), options);
> grub_procfs_register ("luks_script", &luks_script);
> }
> Index: include/grub/cryptodisk.h
> --- grub.orig/include/grub/cryptodisk.h 2014-10-14 23:31:00.000000000 -0300
> +++ grub/include/grub/cryptodisk.h 2015-01-18 00:14:22.572709178 -0200
> @@ -54,6 +54,10 @@ typedef enum
> #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
> #define GRUB_CRYPTODISK_MAX_KEYLEN 128
>
> +/* Backends may limit passphrases to smaller sizes, but this should be
> + the max among them all. */
> +#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
> +
> struct grub_cryptodisk;
>
> typedef gcry_err_code_t
> @@ -107,7 +111,8 @@ struct grub_cryptodisk_dev
>
> grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
> int boot_only);
> - grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
> + grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev,
> + const char *key);
> };
> typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
>
> Index: grub-core/disk/geli.c
> --- grub.orig/grub-core/disk/geli.c 2014-10-14 23:30:57.000000000 -0300
> +++ grub/grub-core/disk/geli.c 2015-01-18 01:06:31.422050391 -0200
> @@ -135,7 +135,7 @@ const char *algorithms[] = {
> [0x16] = "aes"
> };
>
> -#define MAX_PASSPHRASE 256
> +#define MAX_PASSPHRASE GRUB_CRYPTODISK_MAX_PASSPHRASE
>
> static gcry_err_code_t
> geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
> @@ -384,7 +384,7 @@ configure_ciphers (grub_disk_t disk, con
> }
>
> static grub_err_t
> -recover_key (grub_disk_t source, grub_cryptodisk_t dev)
> +recover_key (grub_disk_t source, grub_cryptodisk_t dev, const char *key)
> {
> grub_size_t keysize;
> grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
> @@ -419,16 +419,31 @@ recover_key (grub_disk_t source, grub_cr
>
> grub_puts_ (N_("Attempting to decrypt master key..."));
>
> - /* Get the passphrase from the user. */
> + retry:
> tmp = NULL;
> - if (source->partition)
> - tmp = grub_partition_get_name (source->partition);
> - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> - source->partition ? "," : "", tmp ? : "",
> - dev->uuid);
> - grub_free (tmp);
> - if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> + if (key && grub_strlen (key) >= MAX_PASSPHRASE)
> + {
> + grub_printf_ (N_("Discarding too-long supplied passphrase\n"));
passphrase file?
> + key = NULL;
> + }
> + if (key)
> + {
> + grub_size_t len = grub_strlen (key);
> + grub_memcpy (passphrase, key, len);
> + grub_memset (passphrase + len, 0, sizeof (passphrase) - len);
> + }
> + else
> + {
> + /* Get the passphrase from the user. */
> + if (source->partition)
> + tmp = grub_partition_get_name (source->partition);
> + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> + source->partition ? "," : "", tmp ? : "",
> + dev->uuid);
> + grub_free (tmp);
> + if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> + }
>
> /* Calculate the PBKDF2 of the user supplied passphrase. */
> if (grub_le_to_cpu32 (header.niter) != 0)
> @@ -548,6 +563,13 @@ recover_key (grub_disk_t source, grub_cr
> return GRUB_ERR_NONE;
> }
>
> + if (key)
> + {
> + grub_printf_ (N_("Supplied passphrase failed to unlock key\n"));
"Passphrase file failed to unlock key"?
> + key = NULL;
> + goto retry;
> + }
> +
> return GRUB_ACCESS_DENIED;
> }
>
> Index: grub-core/disk/luks.c
> --- grub.orig/grub-core/disk/luks.c 2014-10-14 23:30:57.000000000 -0300
> +++ grub/grub-core/disk/luks.c 2015-01-18 01:06:26.336192968 -0200
> @@ -29,7 +29,7 @@
>
> GRUB_MOD_LICENSE ("GPLv3+");
>
> -#define MAX_PASSPHRASE 256
> +#define MAX_PASSPHRASE GRUB_CRYPTODISK_MAX_PASSPHRASE
>
> #define LUKS_KEY_ENABLED 0x00AC71F3
>
> @@ -297,7 +297,8 @@ configure_ciphers (grub_disk_t disk, con
>
> static grub_err_t
> luks_recover_key (grub_disk_t source,
> - grub_cryptodisk_t dev)
> + grub_cryptodisk_t dev,
> + const char *key)
> {
> struct grub_luks_phdr header;
> grub_size_t keysize;
> @@ -328,18 +329,33 @@ luks_recover_key (grub_disk_t source,
> if (!split_key)
> return grub_errno;
>
> - /* Get the passphrase from the user. */
> + retry:
> tmp = NULL;
> - if (source->partition)
> - tmp = grub_partition_get_name (source->partition);
> - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> - source->partition ? "," : "", tmp ? : "",
> - dev->uuid);
> - grub_free (tmp);
> - if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> + if (key && grub_strlen (key) >= MAX_PASSPHRASE)
> {
> - grub_free (split_key);
> - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> + grub_printf_ (N_("Discarding too-long supplied passphrase\n"));
passphrase file?
> + key = NULL;
> + }
> + if (key)
> + {
> + grub_size_t len = grub_strlen (key);
> + grub_memcpy (passphrase, key, len);
> + grub_memset (passphrase + len, 0, sizeof (passphrase) - len);
> + }
> + else
> + {
> + /* Get the passphrase from the user. */
> + if (source->partition)
> + tmp = grub_partition_get_name (source->partition);
> + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> + source->partition ? "," : "", tmp ? : "",
> + dev->uuid);
> + grub_free (tmp);
> + if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> + {
> + grub_free (split_key);
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> + }
> }
>
> /* Try to recover master key from each active keyslot. */
> @@ -451,6 +467,13 @@ luks_recover_key (grub_disk_t source,
> return GRUB_ERR_NONE;
> }
>
> + if (key)
> + {
> + grub_printf_ (N_("Supplied passphrase failed to unlock key\n"));
passhprase file
> + key = NULL;
> + goto retry;
> + }
> +
> return GRUB_ACCESS_DENIED;
> }
>
>
>
> --
> Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/ FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: enable cryptomount to read passphrase from file
2015-01-18 14:57 ` Andrei Borzenkov
@ 2015-01-19 6:33 ` Alexandre Oliva
0 siblings, 0 replies; 3+ messages in thread
From: Alexandre Oliva @ 2015-01-19 6:33 UTC (permalink / raw)
To: Andrei Borzenkov; +Cc: grub-devel, John Lane
On Jan 18, 2015, Andrei Borzenkov <arvidjaar@gmail.com> wrote:
> I suggest you cooperate with John for this; he has a set of patches to
> support it as well. See also http://grub.johnlane.ie/.
Nice, for some reason I didn't find his patchset in my web searches. I
ended up using his code to update the crypto modules in libreboot on my
x60, and a slight variant of mine to update them for use along with BLAG
200k's grub on other machines that are not yet running a Free BIOS. If
there's interest, I can post my updated patches here, but I'd be just as
happy if John's patchset made it.
> Just pass in passphrase+len. Do not expect anything about content of
> passphrase file at all.
Done.
> You can always unlock encrypted filesystem manually, right?
As long as grub isn't hosed ;-) In some of my attempts earlier today, it
was. Fortunately I'd saved a working grub on a pen drive, and so
bringing the machine back to a working condition wasn't too hard.
> Hmm ... I'm not sure whether we should fallback to asking user. The whole
> point of using keyfile is to avoid user interaction in the first place,
> right?
Well, sort of. My goal was to let the machine boot up with a pen drive
or entering the key manually, so the fallback made sense. I can get
this effect by just trying with --keyfile first, and without it
afterwards.
>> + else if ((grub_size_t)size >= sizeof (buf))
> Can it be larger than sizeof(buf)?
No, but it doesn't hurt to play safe, does it?
> Is it prohibited to have new line or carriage return in passphrase file?
That was one bit I was uncertain about. Keyboard-entered ones certainly
can't, but there's no reason I can think of to actually exclude them
from files. I was concerned, however, about someone writing a
passphrase normally entered by hand to a file with a trailing newline.
That wouldn't work. The file should not have the trailing newline.
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-01-19 6:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-18 3:29 enable cryptomount to read passphrase from file Alexandre Oliva
2015-01-18 14:57 ` Andrei Borzenkov
2015-01-19 6:33 ` Alexandre Oliva
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.