[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
enable cryptomount to read passphrase from file
From: |
Alexandre Oliva |
Subject: |
enable cryptomount to read passphrase from file |
Date: |
Sun, 18 Jan 2015 01:29:45 -0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
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,
Index: ChangeLog
from Alexandre Oliva <address@hidden>
* 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
address@hidden 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
address@hidden Command cryptomount address@hidden 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
address@hidden the passphrase, not even a trailing line break. Option
address@hidden 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;
}
--
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
- enable cryptomount to read passphrase from file,
Alexandre Oliva <=