All of lore.kernel.org
 help / color / mirror / Atom feed
* Cryptomount enhancements - revised
@ 2015-06-29 14:30 John Lane
  2015-06-29 14:30 ` [PATCH 1/5] Cryptomount support LUKS detached header John Lane
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:30 UTC (permalink / raw)
  To: grub-devel


These patches provide extensions to the "cryptomount" command. There are five patches

 [PATCH 1/5] Cryptomount support LUKS detached header
 Support LUKS detached headers so that the header can be separated from the data payload, e.g. by storing on external removable media such as a USB key.

 [PATCH 2/5] Cryptomount support key files
 Support key files so that passphrase entry can be suppressed. The passphrase can be stored in a "key file" that can be stored, for example, on external removable media such as a USB key.

 [PATCH 3/5] cryptomount luks allow multiple passphrase attempts
 Allow a second attempt to enter a passphrase. If unlocking fails on the first attempt then the user is presented with the passphrase entry prompt again. If a key file is given that does not unlock the device then the user is given the opportunity to enter a passphrase.

 [PATCH 4/5] Cryptomount support plain dm-crypt
 Support plain dm-crypt mode. Allow plain volumes to be opened. This is largely a re-factoring of exisitng code to allow the crypto routines be used independently of LUKS.

 [PATCH 5/5] Cryptomount support for hyphens in UUID
 Support for hyphens in UUID. The "-u" option of cryptomount accepts a UUID. This option allows that to be delimited with hyphens so that the same format can be given to Grub as is passed to the Linux kernel boot options.


This is a revised patch set following feedback from patches sent on 16/6/15.

 grub-core/disk/cryptodisk.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 grub-core/disk/geli.c       |   9 +-
 grub-core/disk/luks.c       | 508 +++++++++++++++++++++++++--------------------------------------------
 include/grub/cryptodisk.h   |  18 ++-
 4 files changed, 581 insertions(+), 336 deletions(-)



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/5] Cryptomount support LUKS detached header
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
@ 2015-06-29 14:30 ` John Lane
  2015-06-29 14:30 ` [PATCH 2/5] Cryptomount support key files John Lane
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:30 UTC (permalink / raw)
  To: grub-devel; +Cc: John Lane

From: John Lane <john@lane.uk.net>

---
 grub-core/disk/cryptodisk.c | 22 ++++++++++++++++++----
 grub-core/disk/geli.c       |  7 +++++--
 grub-core/disk/luks.c       | 45 +++++++++++++++++++++++++++++++++++++--------
 include/grub/cryptodisk.h   |  5 +++--
 4 files changed, 63 insertions(+), 16 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 82a3dcb..6f596a0 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -40,6 +40,7 @@ static const struct grub_arg_option options[] =
     /* 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},
+    {"header", 'H', 0, N_("Read LUKS header from file"), 0, ARG_TYPE_STRING},
     {0, 0, 0, 0, 0, 0}
   };
 
@@ -803,6 +804,7 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
 
 static int check_boot, have_it;
 static char *search_uuid;
+static grub_file_t hdr;
 
 static void
 cryptodisk_close (grub_cryptodisk_t dev)
@@ -827,13 +829,13 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
 
   FOR_CRYPTODISK_DEVS (cr)
   {
-    dev = cr->scan (source, search_uuid, check_boot);
+    dev = cr->scan (source, search_uuid, check_boot, hdr);
     if (grub_errno)
       return grub_errno;
     if (!dev)
       continue;
     
-    err = cr->recover_key (source, dev);
+    err = cr->recover_key (source, dev, hdr);
     if (err)
     {
       cryptodisk_close (dev);
@@ -874,7 +876,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
 
   FOR_CRYPTODISK_DEVS (cr)
   {
-    dev = cr->scan (source, search_uuid, check_boot);
+    dev = cr->scan (source, search_uuid, check_boot,0);
     if (grub_errno)
       return grub_errno;
     if (!dev)
@@ -928,6 +930,18 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
   if (argc < 1 && !state[1].set && !state[2].set)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
 
+  if (state[3].set) /* LUKS detached header */
+    {
+      if (state[0].set) /* Cannot use UUID lookup with detached header */
+        return GRUB_ERR_BAD_ARGUMENT;
+
+      hdr = grub_file_open (state[3].arg);
+      if (!hdr)
+        return grub_errno;
+    }
+  else
+    hdr = NULL;
+
   have_it = 0;
   if (state[0].set)
     {
@@ -1125,7 +1139,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_("SOURCE|-u UUID|-a|-b|-H file"),
 			      N_("Mount a crypto device."), options);
   grub_procfs_register ("luks_script", &luks_script);
 }
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d2329..f4394eb 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -52,6 +52,7 @@
 #include <grub/dl.h>
 #include <grub/err.h>
 #include <grub/disk.h>
+#include <grub/file.h>
 #include <grub/crypto.h>
 #include <grub/partition.h>
 #include <grub/i18n.h>
@@ -243,7 +244,8 @@ grub_util_get_geli_uuid (const char *dev)
 
 static grub_cryptodisk_t
 configure_ciphers (grub_disk_t disk, const char *check_uuid,
-		   int boot_only)
+		   int boot_only,
+		   grub_file_t hdr __attribute__ ((unused)) )
 {
   grub_cryptodisk_t newdev;
   struct grub_geli_phdr header;
@@ -398,7 +400,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 }
 
 static grub_err_t
-recover_key (grub_disk_t source, grub_cryptodisk_t dev)
+recover_key (grub_disk_t source, grub_cryptodisk_t dev,
+	     grub_file_t hdr __attribute__ ((unused)) )
 {
   grub_size_t keysize;
   grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 86c50c6..66e64c0 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -23,6 +23,7 @@
 #include <grub/dl.h>
 #include <grub/err.h>
 #include <grub/disk.h>
+#include <grub/file.h>
 #include <grub/crypto.h>
 #include <grub/partition.h>
 #include <grub/i18n.h>
@@ -66,7 +67,7 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
 
 static grub_cryptodisk_t
 configure_ciphers (grub_disk_t disk, const char *check_uuid,
-		   int check_boot)
+		   int check_boot, grub_file_t hdr)
 {
   grub_cryptodisk_t newdev;
   const char *iptr;
@@ -86,11 +87,21 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   int benbi_log = 0;
   grub_err_t err;
 
+  err = GRUB_ERR_NONE;
+
   if (check_boot)
     return NULL;
 
   /* Read the LUKS header.  */
-  err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
+  if (hdr)
+  {
+    grub_file_seek (hdr, 0);
+    if (grub_file_read (hdr, &header, sizeof (header)) != sizeof (header))
+        err = GRUB_ERR_READ_ERROR;
+  }
+  else
+    err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
+
   if (err)
     {
       if (err == GRUB_ERR_OUT_OF_RANGE)
@@ -304,12 +315,14 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
   newdev->modname = "luks";
   COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
+
   return newdev;
 }
 
 static grub_err_t
 luks_recover_key (grub_disk_t source,
-		  grub_cryptodisk_t dev)
+		  grub_cryptodisk_t dev,
+	          grub_file_t hdr)
 {
   struct grub_luks_phdr header;
   grub_size_t keysize;
@@ -321,8 +334,19 @@ luks_recover_key (grub_disk_t source,
   grub_err_t err;
   grub_size_t max_stripes = 1;
   char *tmp;
+  grub_uint32_t sector;
+
+  err = GRUB_ERR_NONE;
+
+  if (hdr)
+  {
+    grub_file_seek (hdr, 0);
+    if (grub_file_read (hdr, &header, sizeof (header)) != sizeof (header))
+        err = GRUB_ERR_READ_ERROR;
+  }
+  else
+    err = grub_disk_read (source, 0, 0, sizeof (header), &header);
 
-  err = grub_disk_read (source, 0, 0, sizeof (header), &header);
   if (err)
     return err;
 
@@ -391,13 +415,18 @@ luks_recover_key (grub_disk_t source,
 	  return grub_crypto_gcry_error (gcry_err);
 	}
 
+      sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset);
       length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
 
       /* Read and decrypt the key material from the disk.  */
-      err = grub_disk_read (source,
-			    grub_be_to_cpu32 (header.keyblock
-					      [i].keyMaterialOffset), 0,
-			    length, split_key);
+      if (hdr)
+        {
+	  grub_file_seek (hdr, sector * 512);
+          if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length)
+            err = GRUB_ERR_READ_ERROR;
+        }
+      else
+        err = grub_disk_read (source, sector, 0, length, split_key);
       if (err)
 	{
 	  grub_free (split_key);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index f2ad2a7..16dee3c 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -20,6 +20,7 @@
 #define GRUB_CRYPTODISK_HEADER	1
 
 #include <grub/disk.h>
+#include <grub/file.h>
 #include <grub/crypto.h>
 #include <grub/list.h>
 #ifdef GRUB_UTIL
@@ -106,8 +107,8 @@ struct grub_cryptodisk_dev
   struct grub_cryptodisk_dev **prev;
 
   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);
+			     int boot_only, grub_file_t hdr);
+  grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_file_t hdr);
 };
 typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
 
-- 
2.1.2



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/5] Cryptomount support key files
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
  2015-06-29 14:30 ` [PATCH 1/5] Cryptomount support LUKS detached header John Lane
@ 2015-06-29 14:30 ` John Lane
  2015-06-29 14:30 ` [PATCH 3/5] cryptomount luks allow multiple passphrase attempts John Lane
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:30 UTC (permalink / raw)
  To: grub-devel; +Cc: John Lane

From: John Lane <john@lane.uk.net>

---
 grub-core/disk/cryptodisk.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-
 grub-core/disk/geli.c       |  4 +++-
 grub-core/disk/luks.c       | 44 +++++++++++++++++++++++++++++--------------
 include/grub/cryptodisk.h   |  5 ++++-
 4 files changed, 82 insertions(+), 17 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6f596a0..a27e70c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -41,6 +41,9 @@ static const struct grub_arg_option options[] =
     {"all", 'a', 0, N_("Mount all."), 0, 0},
     {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
     {"header", 'H', 0, N_("Read LUKS header from file"), 0, ARG_TYPE_STRING},
+    {"keyfile", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
+    {"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},
     {0, 0, 0, 0, 0, 0}
   };
 
@@ -805,6 +808,8 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
 static int check_boot, have_it;
 static char *search_uuid;
 static grub_file_t hdr;
+static grub_uint8_t *key, keyfile_buffer[GRUB_CRYPTODISK_MAX_KEYFILE_SIZE];
+static grub_size_t keyfile_size;
 
 static void
 cryptodisk_close (grub_cryptodisk_t dev)
@@ -835,7 +840,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
     if (!dev)
       continue;
     
-    err = cr->recover_key (source, dev, hdr);
+    err = cr->recover_key (source, dev, hdr, key, keyfile_size);
     if (err)
     {
       cryptodisk_close (dev);
@@ -943,6 +948,45 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
     hdr = NULL;
 
   have_it = 0;
+  key = NULL;
+
+  if (state[4].set) /* Key file; fails back to passphrase entry */
+    {
+      grub_file_t keyfile;
+      int keyfile_offset;
+      grub_size_t requested_keyfile_size;
+
+      requested_keyfile_size = state[6].set ? grub_strtoul(state[6].arg, 0, 0) : 0;
+
+      if (requested_keyfile_size > GRUB_CRYPTODISK_MAX_KEYFILE_SIZE)
+        grub_printf (N_("Key file size exceeds maximum (%llu)\n"), \
+	                     (unsigned long long) GRUB_CRYPTODISK_MAX_KEYFILE_SIZE);
+      else
+        {
+          keyfile_offset = state[5].set ? grub_strtoul (state[5].arg, 0, 0) : 0;
+          keyfile_size = requested_keyfile_size ? requested_keyfile_size : \
+		                             GRUB_CRYPTODISK_MAX_KEYFILE_SIZE;
+
+          keyfile = grub_file_open (state[4].arg);
+          if (!keyfile)
+            grub_printf (N_("Unable to open key file %s\n"), state[4].arg);
+          else if (grub_file_seek (keyfile, keyfile_offset) == (grub_off_t)-1)
+            grub_printf (N_("Unable to seek to offset %d in key file\n"), keyfile_offset);
+          else
+            {
+              keyfile_size = grub_file_read (keyfile, keyfile_buffer, keyfile_size);
+              if (keyfile_size == (grub_size_t)-1)
+                 grub_printf (N_("Error reading key file\n"));
+	      else if (requested_keyfile_size && (keyfile_size != requested_keyfile_size))
+                 grub_printf (N_("Cannot read %llu bytes for key file (read %llu bytes)\n"),
+                                                (unsigned long long) requested_keyfile_size,
+						(unsigned long long) keyfile_size);
+              else
+                key = keyfile_buffer;
+	    }
+        }
+    }
+
   if (state[0].set)
     {
       grub_cryptodisk_t dev;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index f4394eb..da6aa6a 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -401,7 +401,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
 static grub_err_t
 recover_key (grub_disk_t source, grub_cryptodisk_t dev,
-	     grub_file_t hdr __attribute__ ((unused)) )
+	     grub_file_t hdr __attribute__ ((unused)),
+	     grub_uint8_t *key __attribute__ ((unused)),
+	     grub_size_t keyfile_size __attribute__ ((unused)) )
 {
   grub_size_t keysize;
   grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 66e64c0..5882368 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -322,12 +322,16 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 static grub_err_t
 luks_recover_key (grub_disk_t source,
 		  grub_cryptodisk_t dev,
-	          grub_file_t hdr)
+		  grub_file_t hdr,
+		  grub_uint8_t *keyfile_bytes,
+		  grub_size_t keyfile_bytes_size)
 {
   struct grub_luks_phdr header;
   grub_size_t keysize;
   grub_uint8_t *split_key = NULL;
-  char passphrase[MAX_PASSPHRASE] = "";
+  char interactive_passphrase[MAX_PASSPHRASE] = "";
+  grub_uint8_t *passphrase;
+  grub_size_t passphrase_length;
   grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
   unsigned i;
   grub_size_t length;
@@ -364,18 +368,30 @@ luks_recover_key (grub_disk_t source,
   if (!split_key)
     return grub_errno;
 
-  /* Get the passphrase from the user.  */
-  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 (keyfile_bytes)
     {
-      grub_free (split_key);
-      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+      /* Use bytestring from key file as passphrase */
+      passphrase = keyfile_bytes;
+      passphrase_length = keyfile_bytes_size;
+    }
+  else
+    {
+      /* Get the passphrase from the user.  */
+      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 (interactive_passphrase, MAX_PASSPHRASE))
+        {
+          grub_free (split_key);
+          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+        }
+
+      passphrase = (grub_uint8_t *)interactive_passphrase;
+      passphrase_length = grub_strlen (interactive_passphrase);
+
     }
 
   /* Try to recover master key from each active keyslot.  */
@@ -393,7 +409,7 @@ luks_recover_key (grub_disk_t source,
 
       /* Calculate the PBKDF2 of the user supplied passphrase.  */
       gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
-				     grub_strlen (passphrase),
+				     passphrase_length,
 				     header.keyblock[i].passwordSalt,
 				     sizeof (header.keyblock[i].passwordSalt),
 				     grub_be_to_cpu32 (header.keyblock[i].
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 16dee3c..0299625 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -55,6 +55,8 @@ typedef enum
 #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
 #define GRUB_CRYPTODISK_MAX_KEYLEN 128
 
+#define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192
+
 struct grub_cryptodisk;
 
 typedef gcry_err_code_t
@@ -108,7 +110,8 @@ struct grub_cryptodisk_dev
 
   grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
 			     int boot_only, grub_file_t hdr);
-  grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_file_t hdr);
+  grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev,
+			    grub_file_t hdr, grub_uint8_t *key, grub_size_t keyfile_size);
 };
 typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
 
-- 
2.1.2



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/5] cryptomount luks allow multiple passphrase attempts
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
  2015-06-29 14:30 ` [PATCH 1/5] Cryptomount support LUKS detached header John Lane
  2015-06-29 14:30 ` [PATCH 2/5] Cryptomount support key files John Lane
@ 2015-06-29 14:30 ` John Lane
  2015-06-29 14:56   ` John Lane
  2015-06-29 14:30 ` [PATCH 4/5] Cryptomount support plain dm-crypt John Lane
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: John Lane @ 2015-06-29 14:30 UTC (permalink / raw)
  To: grub-devel; +Cc: John Lane

From: John Lane <john@lane.uk.net>

---
 grub-core/disk/luks.c | 278 ++++++++++++++++++++++++++------------------------
 1 file changed, 143 insertions(+), 135 deletions(-)

diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 5882368..11e437e 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -321,10 +321,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
 static grub_err_t
 luks_recover_key (grub_disk_t source,
-		  grub_cryptodisk_t dev,
-		  grub_file_t hdr,
-		  grub_uint8_t *keyfile_bytes,
-		  grub_size_t keyfile_bytes_size)
+                  grub_cryptodisk_t dev,
+                  grub_file_t hdr,
+                  grub_uint8_t *keyfile_bytes,
+                  grub_size_t keyfile_bytes_size)
 {
   struct grub_luks_phdr header;
   grub_size_t keysize;
@@ -339,6 +339,7 @@ luks_recover_key (grub_disk_t source,
   grub_size_t max_stripes = 1;
   char *tmp;
   grub_uint32_t sector;
+  unsigned attempts = 2;
 
   err = GRUB_ERR_NONE;
 
@@ -361,151 +362,158 @@ luks_recover_key (grub_disk_t source,
 
   for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
     if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
-	&& grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
+        && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
       max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
 
   split_key = grub_malloc (keysize * max_stripes);
   if (!split_key)
     return grub_errno;
 
-  if (keyfile_bytes)
+  while (attempts)
     {
-      /* Use bytestring from key file as passphrase */
-      passphrase = keyfile_bytes;
-      passphrase_length = keyfile_bytes_size;
-    }
-  else
-    {
-      /* Get the passphrase from the user.  */
-      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 (interactive_passphrase, MAX_PASSPHRASE))
+      if (keyfile_bytes)
         {
-          grub_free (split_key);
-          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
-        }
-
-      passphrase = (grub_uint8_t *)interactive_passphrase;
-      passphrase_length = grub_strlen (interactive_passphrase);
-
-    }
-
-  /* Try to recover master key from each active keyslot.  */
-  for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
-    {
-      gcry_err_code_t gcry_err;
-      grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
-      grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
-
-      /* Check if keyslot is enabled.  */
-      if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
-	continue;
-
-      grub_dprintf ("luks", "Trying keyslot %d\n", i);
-
-      /* Calculate the PBKDF2 of the user supplied passphrase.  */
-      gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
-				     passphrase_length,
-				     header.keyblock[i].passwordSalt,
-				     sizeof (header.keyblock[i].passwordSalt),
-				     grub_be_to_cpu32 (header.keyblock[i].
-						       passwordIterations),
-				     digest, keysize);
-
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
-
-      grub_dprintf ("luks", "PBKDF2 done\n");
-
-      gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); 
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
-
-      sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset);
-      length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
-
-      /* Read and decrypt the key material from the disk.  */
-      if (hdr)
-        {
-	  grub_file_seek (hdr, sector * 512);
-          if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length)
-            err = GRUB_ERR_READ_ERROR;
+          /* Use bytestring from key file as passphrase */
+          passphrase = keyfile_bytes;
+          passphrase_length = keyfile_bytes_size;
+	  keyfile_bytes = NULL; /* use it only once */
         }
       else
-        err = grub_disk_read (source, sector, 0, length, split_key);
-      if (err)
-	{
-	  grub_free (split_key);
-	  return err;
-	}
-
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
-
-      /* Merge the decrypted key material to get the candidate master key.  */
-      gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
-			   grub_be_to_cpu32 (header.keyblock[i].stripes));
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
-
-      grub_dprintf ("luks", "candidate key recovered\n");
-
-      /* Calculate the PBKDF2 of the candidate master key.  */
-      gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
-				     grub_be_to_cpu32 (header.keyBytes),
-				     header.mkDigestSalt,
-				     sizeof (header.mkDigestSalt),
-				     grub_be_to_cpu32
-				     (header.mkDigestIterations),
-				     candidate_digest,
-				     sizeof (candidate_digest));
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
-
-      /* Compare the calculated PBKDF2 to the digest stored
-         in the header to see if it's correct.  */
-      if (grub_memcmp (candidate_digest, header.mkDigest,
-		       sizeof (header.mkDigest)) != 0)
-	{
-	  grub_dprintf ("luks", "bad digest\n");
-	  continue;
-	}
+        {
+          /* Get the passphrase from the user.  */
+          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 (interactive_passphrase, MAX_PASSPHRASE))
+            {
+              grub_free (split_key);
+              return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+            }
+
+          passphrase = (grub_uint8_t *)interactive_passphrase;
+          passphrase_length = grub_strlen (interactive_passphrase);
 
-      /* TRANSLATORS: It's a cryptographic key slot: one element of an array
-	 where each element is either empty or holds a key.  */
-      grub_printf_ (N_("Slot %d opened\n"), i);
+        }
 
-      /* Set the master key.  */
-      gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); 
-      if (gcry_err)
-	{
-	  grub_free (split_key);
-	  return grub_crypto_gcry_error (gcry_err);
-	}
+      /* Try to recover master key from each active keyslot.  */
+      for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
+        {
+          gcry_err_code_t gcry_err;
+          grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
+          grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
+
+          /* Check if keyslot is enabled.  */
+          if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
+            continue;
+
+          grub_dprintf ("luks", "Trying keyslot %d\n", i);
+
+          /* Calculate the PBKDF2 of the user supplied passphrase.  */
+          gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
+                                         passphrase_length,
+                                         header.keyblock[i].passwordSalt,
+                                         sizeof (header.keyblock[i].passwordSalt),
+                                         grub_be_to_cpu32 (header.keyblock[i].
+                                         passwordIterations),
+                                         digest, keysize);
+
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
+
+          grub_dprintf ("luks", "PBKDF2 done\n");
+
+          gcry_err = grub_cryptodisk_setkey (dev, digest, keysize);
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
+
+          sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset);
+          length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
+
+          /* Read and decrypt the key material from the disk.  */
+          if (hdr)
+            {
+              grub_file_seek (hdr, sector * 512);
+              if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length)
+                err = GRUB_ERR_READ_ERROR;
+            }
+          else
+            err = grub_disk_read (source, sector, 0, length, split_key);
+          if (err)
+            {
+              grub_free (split_key);
+              return err;
+            }
+
+          gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
+
+          /* Merge the decrypted key material to get the candidate master key.  */
+          gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
+                               grub_be_to_cpu32 (header.keyblock[i].stripes));
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
+
+          grub_dprintf ("luks", "candidate key recovered\n");
+
+          /* Calculate the PBKDF2 of the candidate master key.  */
+          gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
+                                     grub_be_to_cpu32 (header.keyBytes),
+                                     header.mkDigestSalt,
+                                     sizeof (header.mkDigestSalt),
+                                     grub_be_to_cpu32
+                                     (header.mkDigestIterations),
+                                     candidate_digest,
+                                     sizeof (candidate_digest));
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
+
+          /* Compare the calculated PBKDF2 to the digest stored
+             in the header to see if it's correct.  */
+          if (grub_memcmp (candidate_digest, header.mkDigest,
+                                             sizeof (header.mkDigest)) != 0)
+            {
+              grub_dprintf ("luks", "bad digest\n");
+              continue;
+            }
+
+          /* TRANSLATORS: It's a cryptographic key slot: one element of an array
+             where each element is either empty or holds a key.  */
+          grub_printf_ (N_("Slot %d opened\n"), i);
+
+          /* Set the master key.  */
+          gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
+          if (gcry_err)
+            {
+              grub_free (split_key);
+              return grub_crypto_gcry_error (gcry_err);
+            }
 
-      grub_free (split_key);
+          grub_free (split_key);
 
-      return GRUB_ERR_NONE;
+          return GRUB_ERR_NONE;
+        }
+      grub_printf_ (N_("Failed to decrypt master key.\n"));
+      if (--attempts) grub_printf_ (N_("%u attempt%s remaining.\n"), attempts,
+		                    (attempts==1) ? "" : "s");
     }
 
   grub_free (split_key);
-- 
2.1.2



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/5] Cryptomount support plain dm-crypt
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
                   ` (2 preceding siblings ...)
  2015-06-29 14:30 ` [PATCH 3/5] cryptomount luks allow multiple passphrase attempts John Lane
@ 2015-06-29 14:30 ` John Lane
  2016-02-12 15:19   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2015-06-29 14:31 ` [PATCH 5/5] Cryptomount support for hyphens in UUID John Lane
  2015-07-28 18:51 ` Cryptomount enhancements - revised John Lane
  5 siblings, 1 reply; 18+ messages in thread
From: John Lane @ 2015-06-29 14:30 UTC (permalink / raw)
  To: grub-devel; +Cc: John Lane

From: John Lane <john@lane.uk.net>

---
 grub-core/disk/cryptodisk.c | 298 +++++++++++++++++++++++++++++++++++++++++++-
 grub-core/disk/luks.c       | 195 +----------------------------
 include/grub/cryptodisk.h   |   8 ++
 3 files changed, 310 insertions(+), 191 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index a27e70c..cd5cfc9 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -44,6 +44,12 @@ static const struct grub_arg_option options[] =
     {"keyfile", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
     {"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},
+    {"plain", 'p', 0, N_("Plain (no LUKS header)"), 0, ARG_TYPE_NONE},
+    {"cipher", 'c', 0, N_("Plain mode cipher"), 0, ARG_TYPE_STRING},
+    {"digest", 'd', 0, N_("Plain mode passphrase digest (hash)"), 0, ARG_TYPE_STRING},
+    {"offset", 'o', 0, N_("Plain mode data sector offset"), 0, ARG_TYPE_INT},
+    {"size", 's', 0, N_("Size of raw device (sectors, defaults to whole device)"), 0, ARG_TYPE_INT},
+    {"key-size", 'K', 0, N_("Set key size (bits)"), 0, ARG_TYPE_INT},
     {0, 0, 0, 0, 0, 0}
   };
 
@@ -927,6 +933,48 @@ grub_cryptodisk_scan_device (const char *name,
   return have_it && search_uuid ? 1 : 0;
 }
 
+/* Hashes a passphrase into a key and stores it with cipher. */
+static gcry_err_code_t
+set_passphrase (grub_cryptodisk_t dev, grub_size_t keysize, const char *passphrase)
+{
+  grub_uint8_t derived_hash[GRUB_CRYPTODISK_MAX_KEYLEN * 2], *dh = derived_hash;
+  char *p;
+  unsigned int round, i;
+  unsigned int len, size;
+
+  /* Need no passphrase if there's no key */
+  if (keysize == 0)
+    return GPG_ERR_INV_KEYLEN;
+
+  /* Hack to support the "none" hash */
+  if (dev->hash)
+    len = dev->hash->mdlen;
+  else
+    len = grub_strlen (passphrase);
+
+  if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN || len > GRUB_CRYPTODISK_MAX_KEYLEN)
+    return GPG_ERR_INV_KEYLEN;
+
+  p = grub_malloc (grub_strlen (passphrase) + 2 + keysize / len);
+  if (!p)
+    return grub_errno;
+
+  for (round = 0, size = keysize; size; round++, dh += len, size -= len)
+    {
+      for (i = 0; i < round; i++)
+	p[i] = 'A';
+
+      grub_strcpy (p + i, passphrase);
+
+      if (len > size)
+	len = size;
+
+      grub_crypto_hash (dev->hash, dh, p, grub_strlen (p));
+    }
+
+  return grub_cryptodisk_setkey (dev, derived_hash, keysize);
+}
+
 static grub_err_t
 grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
 {
@@ -1046,7 +1094,63 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
 	  return GRUB_ERR_NONE;
 	}
 
-      err = grub_cryptodisk_scan_device_real (args[0], disk);
+      if (state[7].set) /* Plain mode */
+        {
+          char *cipher;
+          char *mode;
+          char *digest;
+          int offset, size, key_size;
+
+          cipher = grub_strdup (state[8].set ? state[8].arg : GRUB_CRYPTODISK_PLAIN_CIPHER);
+          digest = grub_strdup (state[9].set ? state[9].arg : GRUB_CRYPTODISK_PLAIN_DIGEST);
+          offset = state[10].set ? grub_strtoul (state[10].arg, 0, 0) : 0;
+          size   = state[11].set ? grub_strtoul (state[11].arg, 0, 0) : 0;
+          key_size = ( state[12].set ? grub_strtoul (state[12].arg, 0, 0) \
+			             : GRUB_CRYPTODISK_PLAIN_KEYSIZE ) / 8;
+
+          /* no strtok, do it manually */
+          mode = grub_strchr(cipher,'-');
+          if (!mode)
+            return GRUB_ERR_BAD_ARGUMENT;
+          else
+            *mode++ = 0;
+
+          dev = grub_cryptodisk_create (disk, NULL, cipher, mode, digest);
+
+          dev->offset = offset;
+	  if (size) dev->total_length = size;
+
+          if (key)
+	    {
+              err = grub_cryptodisk_setkey (dev, key, key_size);
+              if (err)
+                return err;
+	    }
+	  else
+	    {
+              char passphrase[GRUB_CRYPTODISK_MAX_PASSPHRASE] = "";
+
+              grub_printf_ (N_("Enter passphrase for %s: "), diskname);
+              if (!grub_password_get (passphrase, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+                return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
+
+              err = set_passphrase (dev, key_size, passphrase);
+              if (err)
+                {
+                  grub_crypto_cipher_close (dev->cipher);
+                  return err;
+                }
+	    }
+
+          grub_cryptodisk_insert (dev, diskname, disk);
+
+          grub_free (cipher);
+          grub_free (digest);
+
+          err = GRUB_ERR_NONE;
+        }
+      else
+        err = grub_cryptodisk_scan_device_real (args[0], disk);
 
       grub_disk_close (disk);
 
@@ -1177,13 +1281,203 @@ struct grub_procfs_entry luks_script =
   .get_contents = luks_script_get
 };
 
+grub_cryptodisk_t
+grub_cryptodisk_create (grub_disk_t disk, char *uuid,
+		   char *ciphername, char *ciphermode, char *hashspec)
+{
+  grub_cryptodisk_t newdev;
+  char *cipheriv = NULL;
+  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
+  grub_crypto_cipher_handle_t essiv_cipher = NULL;
+  const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
+  const struct gcry_cipher_spec *ciph;
+  grub_cryptodisk_mode_t mode;
+  grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+  int benbi_log = 0;
+
+  if (!uuid)
+    uuid = (char*)"00000000000000000000000000000000";
+
+  ciph = grub_crypto_lookup_cipher_by_name (ciphername);
+  if (!ciph)
+    {
+      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
+		  ciphername);
+      return NULL;
+    }
+
+  /* Configure the cipher used for the bulk data.  */
+  cipher = grub_crypto_cipher_open (ciph);
+  if (!cipher)
+    return NULL;
+
+  /* Configure the cipher mode.  */
+  if (grub_strcmp (ciphermode, "ecb") == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_ECB;
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+      cipheriv = NULL;
+    }
+  else if (grub_strcmp (ciphermode, "plain") == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_CBC;
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+      cipheriv = NULL;
+    }
+  else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_CBC;
+      cipheriv = ciphermode + sizeof ("cbc-") - 1;
+    }
+  else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_PCBC;
+      cipheriv = ciphermode + sizeof ("pcbc-") - 1;
+    }
+  else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_XTS;
+      cipheriv = ciphermode + sizeof ("xts-") - 1;
+      secondary_cipher = grub_crypto_cipher_open (ciph);
+      if (!secondary_cipher)
+	{
+	  grub_crypto_cipher_close (cipher);
+	  return NULL;
+	}
+      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+	{
+	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
+		      cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
+	  return NULL;
+	}
+      if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+	{
+	  grub_crypto_cipher_close (cipher);
+	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
+		      secondary_cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (secondary_cipher);
+	  return NULL;
+	}
+    }
+  else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
+    {
+      mode = GRUB_CRYPTODISK_MODE_LRW;
+      cipheriv = ciphermode + sizeof ("lrw-") - 1;
+      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
+	{
+	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
+		      cipher->cipher->blocksize);
+	  grub_crypto_cipher_close (cipher);
+	  return NULL;
+	}
+    }
+  else
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
+		  ciphermode);
+      return NULL;
+    }
+
+  if (cipheriv == NULL);
+  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
+  else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+  else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
+    {
+      if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
+	  || cipher->cipher->blocksize == 0)
+	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
+		    cipher->cipher->blocksize);
+	/* FIXME should we return an error here? */
+      for (benbi_log = 0;
+	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
+	   benbi_log++);
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
+    }
+  else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
+  else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
+    {
+      char *hash_str = cipheriv + 6;
+
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
+
+      /* Configure the hash and cipher used for ESSIV.  */
+      essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
+      if (!essiv_hash)
+	{
+	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
+	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
+		      "Couldn't load %s hash", hash_str);
+	  return NULL;
+	}
+      essiv_cipher = grub_crypto_cipher_open (ciph);
+      if (!essiv_cipher)
+	{
+	  grub_crypto_cipher_close (cipher);
+	  grub_crypto_cipher_close (secondary_cipher);
+	  return NULL;
+	}
+    }
+  else
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (secondary_cipher);
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
+		  cipheriv);
+      return NULL;
+    }
+
+  /* Configure the passphrase hash (LUKS also uses AF splitter and HMAC).  */
+  hash = grub_crypto_lookup_md_by_name (hashspec);
+  if (!hash)
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (essiv_cipher);
+      grub_crypto_cipher_close (secondary_cipher);
+      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
+		  hashspec);
+      return NULL;
+    }
+
+  newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
+  if (!newdev)
+    {
+      grub_crypto_cipher_close (cipher);
+      grub_crypto_cipher_close (essiv_cipher);
+      grub_crypto_cipher_close (secondary_cipher);
+      return NULL;
+    }
+  newdev->cipher = cipher;
+  newdev->offset = 0;
+  newdev->source_disk = NULL;
+  newdev->benbi_log = benbi_log;
+  newdev->mode = mode;
+  newdev->mode_iv = mode_iv;
+  newdev->secondary_cipher = secondary_cipher;
+  newdev->essiv_cipher = essiv_cipher;
+  newdev->essiv_hash = essiv_hash;
+  newdev->hash = hash;
+  newdev->log_sector_size = 9;
+  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+  grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
+  COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
+
+  return newdev;
+}
+
 static grub_extcmd_t cmd;
 
 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|-H file"),
+			      N_("SOURCE|-u UUID|-a|-b|-H file|-p -c cipher -d digest"),
 			      N_("Mount a crypto device."), options);
   grub_procfs_register ("luks_script", &luks_script);
 }
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 11e437e..4ebe21b 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -30,8 +30,6 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-#define MAX_PASSPHRASE 256
-
 #define LUKS_KEY_ENABLED  0x00AC71F3
 
 /* On disk LUKS header */
@@ -76,15 +74,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   char uuid[sizeof (header.uuid) + 1];
   char ciphername[sizeof (header.cipherName) + 1];
   char ciphermode[sizeof (header.cipherMode) + 1];
-  char *cipheriv = NULL;
   char hashspec[sizeof (header.hashSpec) + 1];
-  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
-  grub_crypto_cipher_handle_t essiv_cipher = NULL;
-  const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
-  const struct gcry_cipher_spec *ciph;
-  grub_cryptodisk_mode_t mode;
-  grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
-  int benbi_log = 0;
   grub_err_t err;
 
   err = GRUB_ERR_NONE;
@@ -119,7 +109,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
        iptr++)
     {
       if (*iptr != '-')
-	*optr++ = *iptr;
+        *optr++ = *iptr;
     }
   *optr = 0;
 
@@ -129,6 +119,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
     }
 
+
   /* Make sure that strings are null terminated.  */
   grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
   ciphername[sizeof (header.cipherName)] = 0;
@@ -137,184 +128,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
   hashspec[sizeof (header.hashSpec)] = 0;
 
-  ciph = grub_crypto_lookup_cipher_by_name (ciphername);
-  if (!ciph)
-    {
-      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
-		  ciphername);
-      return NULL;
-    }
-
-  /* Configure the cipher used for the bulk data.  */
-  cipher = grub_crypto_cipher_open (ciph);
-  if (!cipher)
-    return NULL;
-
-  if (grub_be_to_cpu32 (header.keyBytes) > 1024)
-    {
-      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
-		  grub_be_to_cpu32 (header.keyBytes));
-      grub_crypto_cipher_close (cipher);
-      return NULL;
-    }
-
-  /* Configure the cipher mode.  */
-  if (grub_strcmp (ciphermode, "ecb") == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_ECB;
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
-      cipheriv = NULL;
-    }
-  else if (grub_strcmp (ciphermode, "plain") == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_CBC;
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
-      cipheriv = NULL;
-    }
-  else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_CBC;
-      cipheriv = ciphermode + sizeof ("cbc-") - 1;
-    }
-  else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_PCBC;
-      cipheriv = ciphermode + sizeof ("pcbc-") - 1;
-    }
-  else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_XTS;
-      cipheriv = ciphermode + sizeof ("xts-") - 1;
-      secondary_cipher = grub_crypto_cipher_open (ciph);
-      if (!secondary_cipher)
-	{
-	  grub_crypto_cipher_close (cipher);
-	  return NULL;
-	}
-      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
-	{
-	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
-		      cipher->cipher->blocksize);
-	  grub_crypto_cipher_close (cipher);
-	  grub_crypto_cipher_close (secondary_cipher);
-	  return NULL;
-	}
-      if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
-	{
-	  grub_crypto_cipher_close (cipher);
-	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
-		      secondary_cipher->cipher->blocksize);
-	  grub_crypto_cipher_close (secondary_cipher);
-	  return NULL;
-	}
-    }
-  else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
-    {
-      mode = GRUB_CRYPTODISK_MODE_LRW;
-      cipheriv = ciphermode + sizeof ("lrw-") - 1;
-      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
-	{
-	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
-		      cipher->cipher->blocksize);
-	  grub_crypto_cipher_close (cipher);
-	  return NULL;
-	}
-    }
-  else
-    {
-      grub_crypto_cipher_close (cipher);
-      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
-		  ciphermode);
-      return NULL;
-    }
-
-  if (cipheriv == NULL);
-  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
-  else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
-  else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
-    {
-      if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
-	  || cipher->cipher->blocksize == 0)
-	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
-		    cipher->cipher->blocksize);
-	/* FIXME should we return an error here? */
-      for (benbi_log = 0; 
-	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
-	   benbi_log++);
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
-    }
-  else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
-  else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
-    {
-      char *hash_str = cipheriv + 6;
-
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
-
-      /* Configure the hash and cipher used for ESSIV.  */
-      essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
-      if (!essiv_hash)
-	{
-	  grub_crypto_cipher_close (cipher);
-	  grub_crypto_cipher_close (secondary_cipher);
-	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
-		      "Couldn't load %s hash", hash_str);
-	  return NULL;
-	}
-      essiv_cipher = grub_crypto_cipher_open (ciph);
-      if (!essiv_cipher)
-	{
-	  grub_crypto_cipher_close (cipher);
-	  grub_crypto_cipher_close (secondary_cipher);
-	  return NULL;
-	}
-    }
-  else
-    {
-      grub_crypto_cipher_close (cipher);
-      grub_crypto_cipher_close (secondary_cipher);
-      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
-		  cipheriv);
-      return NULL;
-    }
-
-  /* Configure the hash used for the AF splitter and HMAC.  */
-  hash = grub_crypto_lookup_md_by_name (hashspec);
-  if (!hash)
-    {
-      grub_crypto_cipher_close (cipher);
-      grub_crypto_cipher_close (essiv_cipher);
-      grub_crypto_cipher_close (secondary_cipher);
-      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
-		  hashspec);
-      return NULL;
-    }
+  newdev = grub_cryptodisk_create (disk, uuid, ciphername, ciphermode, hashspec);
 
-  newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
-  if (!newdev)
-    {
-      grub_crypto_cipher_close (cipher);
-      grub_crypto_cipher_close (essiv_cipher);
-      grub_crypto_cipher_close (secondary_cipher);
-      return NULL;
-    }
-  newdev->cipher = cipher;
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
-  newdev->source_disk = NULL;
-  newdev->benbi_log = benbi_log;
-  newdev->mode = mode;
-  newdev->mode_iv = mode_iv;
-  newdev->secondary_cipher = secondary_cipher;
-  newdev->essiv_cipher = essiv_cipher;
-  newdev->essiv_hash = essiv_hash;
-  newdev->hash = hash;
-  newdev->log_sector_size = 9;
-  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
-  grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
   newdev->modname = "luks";
-  COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
 
   return newdev;
 }
@@ -329,7 +146,7 @@ luks_recover_key (grub_disk_t source,
   struct grub_luks_phdr header;
   grub_size_t keysize;
   grub_uint8_t *split_key = NULL;
-  char interactive_passphrase[MAX_PASSPHRASE] = "";
+  char interactive_passphrase[GRUB_CRYPTODISK_MAX_PASSPHRASE] = "";
   grub_uint8_t *passphrase;
   grub_size_t passphrase_length;
   grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
@@ -376,7 +193,7 @@ luks_recover_key (grub_disk_t source,
           /* Use bytestring from key file as passphrase */
           passphrase = keyfile_bytes;
           passphrase_length = keyfile_bytes_size;
-	  keyfile_bytes = NULL; /* use it only once */
+          keyfile_bytes = NULL; /* use it only once */
         }
       else
         {
@@ -387,7 +204,7 @@ luks_recover_key (grub_disk_t source,
           grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
                               source->partition ? "," : "", tmp ? : "", dev->uuid);
           grub_free (tmp);
-          if (!grub_password_get (interactive_passphrase, MAX_PASSPHRASE))
+          if (!grub_password_get (interactive_passphrase, GRUB_CRYPTODISK_MAX_PASSPHRASE))
             {
               grub_free (split_key);
               return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 0299625..4076412 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -54,9 +54,14 @@ typedef enum
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
 #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
 #define GRUB_CRYPTODISK_MAX_KEYLEN 128
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
 
 #define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192
 
+#define GRUB_CRYPTODISK_PLAIN_CIPHER  "aes-cbc-essiv:sha256"
+#define GRUB_CRYPTODISK_PLAIN_DIGEST  "ripemd160"
+#define GRUB_CRYPTODISK_PLAIN_KEYSIZE 256
+
 struct grub_cryptodisk;
 
 typedef gcry_err_code_t
@@ -159,4 +164,7 @@ grub_util_get_geli_uuid (const char *dev);
 grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
 grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
 
+grub_cryptodisk_t grub_cryptodisk_create (grub_disk_t disk, char *uuid,
+				   char *ciphername, char *ciphermode, char *digest);
+
 #endif
-- 
2.1.2



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
                   ` (3 preceding siblings ...)
  2015-06-29 14:30 ` [PATCH 4/5] Cryptomount support plain dm-crypt John Lane
@ 2015-06-29 14:31 ` John Lane
  2015-06-29 14:52   ` John Lane
  2015-07-29  3:08   ` Andrei Borzenkov
  2015-07-28 18:51 ` Cryptomount enhancements - revised John Lane
  5 siblings, 2 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:31 UTC (permalink / raw)
  To: grub-devel; +Cc: John Lane

From: John Lane <john@lane.uk.net>

---
 grub-core/disk/cryptodisk.c | 20 +++++++++++++++++---
 grub-core/disk/luks.c       | 26 ++++++++------------------
 include/grub/cryptodisk.h   |  2 ++
 3 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index cd5cfc9..d36d16b 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -113,6 +113,20 @@ gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b)
     }
 }
 
+int
+grub_cryptodisk_uuidcmp(char *uuid_a, char *uuid_b)
+{
+  while ((*uuid_a != '\0') && (*uuid_b != '\0'))
+    {
+      while (*uuid_a == '-') uuid_a++;
+      while (*uuid_b == '-') uuid_b++;
+      if (grub_toupper(*uuid_a) != grub_toupper(*uuid_b)) break;
+      uuid_a++;
+      uuid_b++;
+    }
+  return (*uuid_a == '\0') && (*uuid_b == '\0');
+}
+
 static gcry_err_code_t
 grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
 			 void *out, void *in, grub_size_t size,
@@ -507,8 +521,8 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
   if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
     {
       for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
-	if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
-	  break;
+        if (grub_cryptodisk_uuidcmp(name + sizeof ("cryptouuid/") - 1, dev->uuid))
+          break;
     }
   else
     {
@@ -739,7 +753,7 @@ grub_cryptodisk_get_by_uuid (const char *uuid)
 {
   grub_cryptodisk_t dev;
   for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
-    if (grub_strcasecmp (dev->uuid, uuid) == 0)
+    if (grub_cryptodisk_uuidcmp(dev->uuid, uuid))
       return dev;
   return NULL;
 }
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 4ebe21b..80a7606 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -68,9 +68,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 		   int check_boot, grub_file_t hdr)
 {
   grub_cryptodisk_t newdev;
-  const char *iptr;
   struct grub_luks_phdr header;
-  char *optr;
   char uuid[sizeof (header.uuid) + 1];
   char ciphername[sizeof (header.cipherName) + 1];
   char ciphermode[sizeof (header.cipherMode) + 1];
@@ -104,22 +102,6 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       || grub_be_to_cpu16 (header.version) != 1)
     return NULL;
 
-  optr = uuid;
-  for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
-       iptr++)
-    {
-      if (*iptr != '-')
-        *optr++ = *iptr;
-    }
-  *optr = 0;
-
-  if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
-    {
-      grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
-      return NULL;
-    }
-
-
   /* Make sure that strings are null terminated.  */
   grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
   ciphername[sizeof (header.cipherName)] = 0;
@@ -127,6 +109,14 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   ciphermode[sizeof (header.cipherMode)] = 0;
   grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
   hashspec[sizeof (header.hashSpec)] = 0;
+  grub_memcpy (uuid, header.uuid, sizeof (header.uuid));
+  uuid[sizeof (header.uuid)] = 0;
+
+  if ( check_uuid && ! grub_cryptodisk_uuidcmp(check_uuid, uuid))
+    {
+      grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
+      return NULL;
+    }
 
   newdev = grub_cryptodisk_create (disk, uuid, ciphername, ciphermode, hashspec);
 
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 4076412..a564f2c 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -167,4 +167,6 @@ grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
 grub_cryptodisk_t grub_cryptodisk_create (grub_disk_t disk, char *uuid,
 				   char *ciphername, char *ciphermode, char *digest);
 
+int
+grub_cryptodisk_uuidcmp(char *uuid_a, char *uuid_b);
 #endif
-- 
2.1.2



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-06-29 14:31 ` [PATCH 5/5] Cryptomount support for hyphens in UUID John Lane
@ 2015-06-29 14:52   ` John Lane
  2015-07-29  3:08   ` Andrei Borzenkov
  1 sibling, 0 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:52 UTC (permalink / raw)
  To: grub-devel

This revised patch uses a compare function. It doesn't modify the input
supplied by the user.

There are 3 places where UUIDs are compared:
1. when a crypto disk is referenced as a (cryptouuid/...) #cryotodisk.c
grub_cryptodisk_open
2. when the -u argument is given to cryptomount it checks by the uuid
that the device isn't already mounted #cryptodisk.c
grub_cryptodisk_get_by_uuid
3. when locating a device by uuid it compares the given uuid with the
LUKS header #luks.c configure_ciphers







^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/5] cryptomount luks allow multiple passphrase attempts
  2015-06-29 14:30 ` [PATCH 3/5] cryptomount luks allow multiple passphrase attempts John Lane
@ 2015-06-29 14:56   ` John Lane
  0 siblings, 0 replies; 18+ messages in thread
From: John Lane @ 2015-06-29 14:56 UTC (permalink / raw)
  To: grub-devel

When opening a LUKS volume the user has 2 chances to supply a correct
passphrase.

if the first attempt fails then the passphrase prompt appears again.
if keyfile given then the first attempt is the uses that instead of
prompting; failure will then prompt the user for a passphrase.

This does not apply to plain mode because there is no way to know that a
key is incorrect in plain mode. Whatever key or passphrase is given will
succeed (but the unlocked data may appear as garbage, of course.).
That's inherent in the implementation of plain mode.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Cryptomount enhancements - revised
  2015-06-29 14:30 Cryptomount enhancements - revised John Lane
                   ` (4 preceding siblings ...)
  2015-06-29 14:31 ` [PATCH 5/5] Cryptomount support for hyphens in UUID John Lane
@ 2015-07-28 18:51 ` John Lane
  2015-07-28 21:38   ` Vladimir 'phcoder' Serbinenko
  5 siblings, 1 reply; 18+ messages in thread
From: John Lane @ 2015-07-28 18:51 UTC (permalink / raw)
  To: grub-devel

On 29/06/15 15:30, John Lane wrote:
> These patches provide extensions to the "cryptomount" command. There are five patches
>
>  [PATCH 1/5] Cryptomount support LUKS detached header
>  Support LUKS detached headers so that the header can be separated from the data payload, e.g. by storing on external removable media such as a USB key.
>
>  [PATCH 2/5] Cryptomount support key files
>  Support key files so that passphrase entry can be suppressed. The passphrase can be stored in a "key file" that can be stored, for example, on external removable media such as a USB key.
>
>  [PATCH 3/5] cryptomount luks allow multiple passphrase attempts
>  Allow a second attempt to enter a passphrase. If unlocking fails on the first attempt then the user is presented with the passphrase entry prompt again. If a key file is given that does not unlock the device then the user is given the opportunity to enter a passphrase.
>
>  [PATCH 4/5] Cryptomount support plain dm-crypt
>  Support plain dm-crypt mode. Allow plain volumes to be opened. This is largely a re-factoring of exisitng code to allow the crypto routines be used independently of LUKS.
>
>  [PATCH 5/5] Cryptomount support for hyphens in UUID
>  Support for hyphens in UUID. The "-u" option of cryptomount accepts a UUID. This option allows that to be delimited with hyphens so that the same format can be given to Grub as is passed to the Linux kernel boot options.
>
>
> This is a revised patch set following feedback from patches sent on 16/6/15.
>
>  grub-core/disk/cryptodisk.c | 382 ++++++++++++++++++++++++++++++++++++++++++++++++++--
>  grub-core/disk/geli.c       |   9 +-
>  grub-core/disk/luks.c       | 508 +++++++++++++++++++++++++--------------------------------------------
>  include/grub/cryptodisk.h   |  18 ++-
>  4 files changed, 581 insertions(+), 336 deletions(-)
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
Just wondering if there's any feedback on these patches... It's been a
while since I posted them.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Cryptomount enhancements - revised
  2015-07-28 18:51 ` Cryptomount enhancements - revised John Lane
@ 2015-07-28 21:38   ` Vladimir 'phcoder' Serbinenko
  2015-07-29  6:48     ` John Lane
  0 siblings, 1 reply; 18+ messages in thread
From: Vladimir 'phcoder' Serbinenko @ 2015-07-28 21:38 UTC (permalink / raw)
  To: The development of GRUB 2

[-- Attachment #1: Type: text/plain, Size: 2736 bytes --]

Other than 3 and 5 they require difficult configuration. Mapping devices in
GRUB isn't trivial. Those features are difficult to autoconfigure. Consider
"plain" mode: how will you find which disk is yours when you have 5 disks
all looking as random data?
Le 28 juil. 2015 8:59 PM, "John Lane" <grub@jelmail.com> a écrit :

> On 29/06/15 15:30, John Lane wrote:
> > These patches provide extensions to the "cryptomount" command. There are
> five patches
> >
> >  [PATCH 1/5] Cryptomount support LUKS detached header
> >  Support LUKS detached headers so that the header can be separated from
> the data payload, e.g. by storing on external removable media such as a USB
> key.
> >
> >  [PATCH 2/5] Cryptomount support key files
> >  Support key files so that passphrase entry can be suppressed. The
> passphrase can be stored in a "key file" that can be stored, for example,
> on external removable media such as a USB key.
> >
> >  [PATCH 3/5] cryptomount luks allow multiple passphrase attempts
> >  Allow a second attempt to enter a passphrase. If unlocking fails on the
> first attempt then the user is presented with the passphrase entry prompt
> again. If a key file is given that does not unlock the device then the user
> is given the opportunity to enter a passphrase.
> >
> >  [PATCH 4/5] Cryptomount support plain dm-crypt
> >  Support plain dm-crypt mode. Allow plain volumes to be opened. This is
> largely a re-factoring of exisitng code to allow the crypto routines be
> used independently of LUKS.
> >
> >  [PATCH 5/5] Cryptomount support for hyphens in UUID
> >  Support for hyphens in UUID. The "-u" option of cryptomount accepts a
> UUID. This option allows that to be delimited with hyphens so that the same
> format can be given to Grub as is passed to the Linux kernel boot options.
> >
> >
> > This is a revised patch set following feedback from patches sent on
> 16/6/15.
> >
> >  grub-core/disk/cryptodisk.c | 382
> ++++++++++++++++++++++++++++++++++++++++++++++++++--
> >  grub-core/disk/geli.c       |   9 +-
> >  grub-core/disk/luks.c       | 508
> +++++++++++++++++++++++++--------------------------------------------
> >  include/grub/cryptodisk.h   |  18 ++-
> >  4 files changed, 581 insertions(+), 336 deletions(-)
> >
> >
> > _______________________________________________
> > Grub-devel mailing list
> > Grub-devel@gnu.org
> > https://lists.gnu.org/mailman/listinfo/grub-devel
> >
> Just wondering if there's any feedback on these patches... It's been a
> while since I posted them.
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>

[-- Attachment #2: Type: text/html, Size: 3459 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-06-29 14:31 ` [PATCH 5/5] Cryptomount support for hyphens in UUID John Lane
  2015-06-29 14:52   ` John Lane
@ 2015-07-29  3:08   ` Andrei Borzenkov
  2015-07-29  6:51     ` John Lane
  1 sibling, 1 reply; 18+ messages in thread
From: Andrei Borzenkov @ 2015-07-29  3:08 UTC (permalink / raw)
  To: John Lane; +Cc: grub-devel, John Lane


I still believe that generally ignoring hyphens for every future crypto
implementation is wrong. In future we simply should avoid mangling
UUID. So this should be restricted to LUKS only, where the problem
exists.

В Mon, 29 Jun 2015 15:31:00 +0100
John Lane <grub@jelmail.com> пишет:

> From: John Lane <john@lane.uk.net>
> 
> ---
>  grub-core/disk/cryptodisk.c | 20 +++++++++++++++++---
>  grub-core/disk/luks.c       | 26 ++++++++------------------
>  include/grub/cryptodisk.h   |  2 ++
>  3 files changed, 27 insertions(+), 21 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index cd5cfc9..d36d16b 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -113,6 +113,20 @@ gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b)
>      }
>  }
>  
> +int
> +grub_cryptodisk_uuidcmp(char *uuid_a, char *uuid_b)
> +{
> +  while ((*uuid_a != '\0') && (*uuid_b != '\0'))
> +    {
> +      while (*uuid_a == '-') uuid_a++;
> +      while (*uuid_b == '-') uuid_b++;
> +      if (grub_toupper(*uuid_a) != grub_toupper(*uuid_b)) break;
> +      uuid_a++;
> +      uuid_b++;
> +    }
> +  return (*uuid_a == '\0') && (*uuid_b == '\0');
> +}
> +
>  static gcry_err_code_t
>  grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
>  			 void *out, void *in, grub_size_t size,
> @@ -507,8 +521,8 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
>    if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
>      {
>        for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
> -	if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
> -	  break;
> +        if (grub_cryptodisk_uuidcmp(name + sizeof ("cryptouuid/") - 1, dev->uuid))
> +          break;
>      }
>    else
>      {
> @@ -739,7 +753,7 @@ grub_cryptodisk_get_by_uuid (const char *uuid)
>  {
>    grub_cryptodisk_t dev;
>    for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
> -    if (grub_strcasecmp (dev->uuid, uuid) == 0)
> +    if (grub_cryptodisk_uuidcmp(dev->uuid, uuid))
>        return dev;
>    return NULL;
>  }
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 4ebe21b..80a7606 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -68,9 +68,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>  		   int check_boot, grub_file_t hdr)
>  {
>    grub_cryptodisk_t newdev;
> -  const char *iptr;
>    struct grub_luks_phdr header;
> -  char *optr;
>    char uuid[sizeof (header.uuid) + 1];
>    char ciphername[sizeof (header.cipherName) + 1];
>    char ciphermode[sizeof (header.cipherMode) + 1];
> @@ -104,22 +102,6 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        || grub_be_to_cpu16 (header.version) != 1)
>      return NULL;
>  
> -  optr = uuid;
> -  for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
> -       iptr++)
> -    {
> -      if (*iptr != '-')
> -        *optr++ = *iptr;
> -    }
> -  *optr = 0;
> -
> -  if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
> -    {
> -      grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
> -      return NULL;
> -    }
> -
> -
>    /* Make sure that strings are null terminated.  */
>    grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
>    ciphername[sizeof (header.cipherName)] = 0;
> @@ -127,6 +109,14 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    ciphermode[sizeof (header.cipherMode)] = 0;
>    grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
>    hashspec[sizeof (header.hashSpec)] = 0;
> +  grub_memcpy (uuid, header.uuid, sizeof (header.uuid));
> +  uuid[sizeof (header.uuid)] = 0;
> +
> +  if ( check_uuid && ! grub_cryptodisk_uuidcmp(check_uuid, uuid))
> +    {
> +      grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
> +      return NULL;
> +    }
>  
>    newdev = grub_cryptodisk_create (disk, uuid, ciphername, ciphermode, hashspec);
>  
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 4076412..a564f2c 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -167,4 +167,6 @@ grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
>  grub_cryptodisk_t grub_cryptodisk_create (grub_disk_t disk, char *uuid,
>  				   char *ciphername, char *ciphermode, char *digest);
>  
> +int
> +grub_cryptodisk_uuidcmp(char *uuid_a, char *uuid_b);
>  #endif



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Cryptomount enhancements - revised
  2015-07-28 21:38   ` Vladimir 'phcoder' Serbinenko
@ 2015-07-29  6:48     ` John Lane
  2015-07-29 17:21       ` Andrei Borzenkov
  0 siblings, 1 reply; 18+ messages in thread
From: John Lane @ 2015-07-29  6:48 UTC (permalink / raw)
  To: grub-devel

On 28/07/15 22:38, Vladimir 'phcoder' Serbinenko wrote:
>
> Other than 3 and 5 they require difficult configuration. Mapping
> devices in GRUB isn't trivial. Those features are difficult to
> autoconfigure. Consider "plain" mode: how will you find which disk is
> yours when you have 5 disks all looking as random data?
>
>
I don't see what's difficult about providing a LUKs header and key but I
am aware of the issue re device identification in plain mode. However,
if one has a use-case for these crypto routines then I think that would
be a valid use-case for manually configuring grub.cfg if it's beyond
what autoconfiguration supports. If an end user wants to make the choice
then why deny him, just because it may be difficult to autoconfigure ?

There does seem to be interest in this functionality. Surely
auto-configuration would't be a bar to supporting this? I don't think I
am the only one who thinks these features are useful...

Regarding device identification, I had some thoughts on that and was
willing to try implementing something. However I wanted to put this
patch-set to bed before starting on something else.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-07-29  3:08   ` Andrei Borzenkov
@ 2015-07-29  6:51     ` John Lane
  2015-07-29 16:51       ` Andrei Borzenkov
  0 siblings, 1 reply; 18+ messages in thread
From: John Lane @ 2015-07-29  6:51 UTC (permalink / raw)
  To: Andrei Borzenkov; +Cc: grub-devel

On 29/07/15 04:08, Andrei Borzenkov wrote:
> I still believe that generally ignoring hyphens for every future crypto
> implementation is wrong. In future we simply should avoid mangling
> UUID. So this should be restricted to LUKS only, where the problem
> exists.
>
>
Andrei I modified this in response to your earlier feedback so that it
doesn't modify the user-supplied data and doesn't have any effect beyond
the three places I mentioned. These have no negative impact on uuid
values used elesewere. If you don't want to support this fair enough -
this can be dropped without impacting the other patches.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-07-29  6:51     ` John Lane
@ 2015-07-29 16:51       ` Andrei Borzenkov
  2015-07-29 18:53         ` John Lane
  0 siblings, 1 reply; 18+ messages in thread
From: Andrei Borzenkov @ 2015-07-29 16:51 UTC (permalink / raw)
  To: John Lane; +Cc: grub-devel

В Wed, 29 Jul 2015 07:51:44 +0100
John Lane <grub@jelmail.com> пишет:

> On 29/07/15 04:08, Andrei Borzenkov wrote:
> > I still believe that generally ignoring hyphens for every future crypto
> > implementation is wrong. In future we simply should avoid mangling
> > UUID. So this should be restricted to LUKS only, where the problem
> > exists.
> >
> >
> Andrei I modified this in response to your earlier feedback so that it
> doesn't modify the user-supplied data and doesn't have any effect beyond
> the three places I mentioned.

That not what I mean. This patch ignores hyphens in UUID for any
current and future crypto backends. This means that it cannot
distinguish between 11-122 and 111-22 as UUID. And we cannot be sure we
never meet such backend. And GELI as far as I can tell does not
actually use hyphens.

We already made mistake of mangling native UUID, I'd rather avoid
continue to do it.

Can we restrict this to LUKS only? 

>                              These have no negative impact on uuid
> values used elesewere. If you don't want to support this fair enough -
> this can be dropped without impacting the other patches.
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Cryptomount enhancements - revised
  2015-07-29  6:48     ` John Lane
@ 2015-07-29 17:21       ` Andrei Borzenkov
  2015-08-01 16:22         ` John Lane
  0 siblings, 1 reply; 18+ messages in thread
From: Andrei Borzenkov @ 2015-07-29 17:21 UTC (permalink / raw)
  To: John Lane; +Cc: grub-devel

В Wed, 29 Jul 2015 07:48:41 +0100
John Lane <grub@jelmail.com> пишет:

> On 28/07/15 22:38, Vladimir 'phcoder' Serbinenko wrote:
> >
> > Other than 3 and 5 they require difficult configuration. Mapping
> > devices in GRUB isn't trivial. Those features are difficult to
> > autoconfigure. Consider "plain" mode: how will you find which disk is
> > yours when you have 5 disks all looking as random data?
> >
> >
> I don't see what's difficult about providing a LUKs header and key but I
> am aware of the issue re device identification in plain mode. However,
> if one has a use-case for these crypto routines then I think that would
> be a valid use-case for manually configuring grub.cfg if it's beyond
> what autoconfiguration supports. If an end user wants to make the choice
> then why deny him, just because it may be difficult to autoconfigure ?
> 

Yes, it appears people ask for it. At the end, the worst that can
happen is reading garbage.

> There does seem to be interest in this functionality. Surely
> auto-configuration would't be a bar to supporting this? I don't think I
> am the only one who thinks these features are useful...
> 
> Regarding device identification, I had some thoughts on that and was
> willing to try implementing something. However I wanted to put this
> patch-set to bed before starting on something else.
> 

One think I'd like is to separate self-identified containers managed by
cryptomount and dmsetup-like stuff to avoid impression that it is fully
supported.


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/5] Cryptomount support for hyphens in UUID
  2015-07-29 16:51       ` Andrei Borzenkov
@ 2015-07-29 18:53         ` John Lane
  0 siblings, 0 replies; 18+ messages in thread
From: John Lane @ 2015-07-29 18:53 UTC (permalink / raw)
  To: Andrei Borzenkov; +Cc: grub-devel

On 29/07/15 17:51, Andrei Borzenkov wrote:
>
> That not what I mean. This patch ignores hyphens in UUID for any
> current and future crypto backends. This means that it cannot
> distinguish between 11-122 and 111-22 as UUID. And we cannot be sure we
> never meet such backend. 
do you really think that's likely?
> And GELI as far as I can tell does not
> actually use hyphens.
>
> We already made mistake of mangling native UUID, I'd rather avoid
> continue to do it.
>
> Can we restrict this to LUKS only? 
One of the three places that UUIDs are compared is in the LUKS module.
The other two are in the generic cryptodisk module, one when the "-u"
argument is given (which I believe is LUKS-specific although not in the
LUKS module) and the other when a crypto disk is referenced as a
(cryptouuid/...) which is generic code, not LUKS-specific. Making it
LUKS-specific would mean deleting the third case, which is actually the
most useful IMHO.

Unless we could identify a LUKS disk from within a grub_cryptodisk_t but
I don't think that's possible ?
If it were, we could make the "uuidcmp" function accept an
"ignore-hyphens" parameter that is true for LUKS and false for
everything else.

But it all seems to be getting overcomplicated for what was meant to be
a simple tweak.





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Cryptomount enhancements - revised
  2015-07-29 17:21       ` Andrei Borzenkov
@ 2015-08-01 16:22         ` John Lane
  0 siblings, 0 replies; 18+ messages in thread
From: John Lane @ 2015-08-01 16:22 UTC (permalink / raw)
  To: Andrei Borzenkov; +Cc: grub-devel

On 29/07/15 18:21, Andrei Borzenkov wrote:
> В Wed, 29 Jul 2015 07:48:41 +0100
> John Lane <grub@jelmail.com> пишет:
>
>> On 28/07/15 22:38, Vladimir 'phcoder' Serbinenko wrote:
>>> Other than 3 and 5 they require difficult configuration. Mapping
>>> devices in GRUB isn't trivial. Those features are difficult to
>>> autoconfigure. Consider "plain" mode: how will you find which disk is
>>> yours when you have 5 disks all looking as random data?
>>>
>>>
>> I don't see what's difficult about providing a LUKs header and key but I
>> am aware of the issue re device identification in plain mode. However,
>> if one has a use-case for these crypto routines then I think that would
>> be a valid use-case for manually configuring grub.cfg if it's beyond
>> what autoconfiguration supports. If an end user wants to make the choice
>> then why deny him, just because it may be difficult to autoconfigure ?
>>
> Yes, it appears people ask for it. At the end, the worst that can
> happen is reading garbage.
>
>> There does seem to be interest in this functionality. Surely
>> auto-configuration would't be a bar to supporting this? I don't think I
>> am the only one who thinks these features are useful...
>>
>> Regarding device identification, I had some thoughts on that and was
>> willing to try implementing something. However I wanted to put this
>> patch-set to bed before starting on something else.
>>
> One think I'd like is to separate self-identified containers managed by
> cryptomount and dmsetup-like stuff to avoid impression that it is fully
> supported.
>
I'm unclear on what the next step is, having responded to feedback and
made changes to address the issues previously raised. Is anything
outstanding that absolutely has to happen before these patches can be
accepted?

Ideally I'd prefer to wrap up this set of changes up before thinking
about other features.



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/5] Cryptomount support plain dm-crypt
  2015-06-29 14:30 ` [PATCH 4/5] Cryptomount support plain dm-crypt John Lane
@ 2016-02-12 15:19   ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2016-02-12 15:19 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 23641 bytes --]

On 29.06.2015 16:30, John Lane wrote:
> From: John Lane <john@lane.uk.net>
> 
> ---
>  grub-core/disk/cryptodisk.c | 298 +++++++++++++++++++++++++++++++++++++++++++-
>  grub-core/disk/luks.c       | 195 +----------------------------
>  include/grub/cryptodisk.h   |   8 ++
>  3 files changed, 310 insertions(+), 191 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index a27e70c..cd5cfc9 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -44,6 +44,12 @@ static const struct grub_arg_option options[] =
>      {"keyfile", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
>      {"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},
> +    {"plain", 'p', 0, N_("Plain (no LUKS header)"), 0, ARG_TYPE_NONE},
> +    {"cipher", 'c', 0, N_("Plain mode cipher"), 0, ARG_TYPE_STRING},
> +    {"digest", 'd', 0, N_("Plain mode passphrase digest (hash)"), 0, ARG_TYPE_STRING},
> +    {"offset", 'o', 0, N_("Plain mode data sector offset"), 0, ARG_TYPE_INT},
> +    {"size", 's', 0, N_("Size of raw device (sectors, defaults to whole device)"), 0, ARG_TYPE_INT},
> +    {"key-size", 'K', 0, N_("Set key size (bits)"), 0, ARG_TYPE_INT},
>      {0, 0, 0, 0, 0, 0}
>    };
>  
This is hairy, doesn't fit into cryptomount syntax and not maintainable.
Can we have a separate command for this?
> @@ -927,6 +933,48 @@ grub_cryptodisk_scan_device (const char *name,
>    return have_it && search_uuid ? 1 : 0;
>  }
>  
> +/* Hashes a passphrase into a key and stores it with cipher. */
> +static gcry_err_code_t
> +set_passphrase (grub_cryptodisk_t dev, grub_size_t keysize, const char *passphrase)
> +{
> +  grub_uint8_t derived_hash[GRUB_CRYPTODISK_MAX_KEYLEN * 2], *dh = derived_hash;
> +  char *p;
> +  unsigned int round, i;
> +  unsigned int len, size;
> +
> +  /* Need no passphrase if there's no key */
> +  if (keysize == 0)
> +    return GPG_ERR_INV_KEYLEN;
> +
> +  /* Hack to support the "none" hash */
> +  if (dev->hash)
> +    len = dev->hash->mdlen;
> +  else
> +    len = grub_strlen (passphrase);
> +
> +  if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN || len > GRUB_CRYPTODISK_MAX_KEYLEN)
> +    return GPG_ERR_INV_KEYLEN;
> +
> +  p = grub_malloc (grub_strlen (passphrase) + 2 + keysize / len);
> +  if (!p)
> +    return grub_errno;
> +
> +  for (round = 0, size = keysize; size; round++, dh += len, size -= len)
> +    {
> +      for (i = 0; i < round; i++)
> +	p[i] = 'A';
> +
> +      grub_strcpy (p + i, passphrase);
> +
> +      if (len > size)
> +	len = size;
> +
> +      grub_crypto_hash (dev->hash, dh, p, grub_strlen (p));
> +    }
> +
> +  return grub_cryptodisk_setkey (dev, derived_hash, keysize);
> +}
> +
>  static grub_err_t
>  grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
>  {
> @@ -1046,7 +1094,63 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
>  	  return GRUB_ERR_NONE;
>  	}
>  
> -      err = grub_cryptodisk_scan_device_real (args[0], disk);
> +      if (state[7].set) /* Plain mode */
> +        {
> +          char *cipher;
> +          char *mode;
> +          char *digest;
> +          int offset, size, key_size;
> +
> +          cipher = grub_strdup (state[8].set ? state[8].arg : GRUB_CRYPTODISK_PLAIN_CIPHER);
> +          digest = grub_strdup (state[9].set ? state[9].arg : GRUB_CRYPTODISK_PLAIN_DIGEST);
> +          offset = state[10].set ? grub_strtoul (state[10].arg, 0, 0) : 0;
> +          size   = state[11].set ? grub_strtoul (state[11].arg, 0, 0) : 0;
> +          key_size = ( state[12].set ? grub_strtoul (state[12].arg, 0, 0) \
> +			             : GRUB_CRYPTODISK_PLAIN_KEYSIZE ) / 8;
> +
> +          /* no strtok, do it manually */
> +          mode = grub_strchr(cipher,'-');
> +          if (!mode)
> +            return GRUB_ERR_BAD_ARGUMENT;
> +          else
> +            *mode++ = 0;
> +
> +          dev = grub_cryptodisk_create (disk, NULL, cipher, mode, digest);
> +
> +          dev->offset = offset;
> +	  if (size) dev->total_length = size;
> +
> +          if (key)
> +	    {
> +              err = grub_cryptodisk_setkey (dev, key, key_size);
> +              if (err)
> +                return err;
> +	    }
> +	  else
> +	    {
> +              char passphrase[GRUB_CRYPTODISK_MAX_PASSPHRASE] = "";
> +
> +              grub_printf_ (N_("Enter passphrase for %s: "), diskname);
> +              if (!grub_password_get (passphrase, GRUB_CRYPTODISK_MAX_PASSPHRASE))
> +                return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> +
> +              err = set_passphrase (dev, key_size, passphrase);
> +              if (err)
> +                {
> +                  grub_crypto_cipher_close (dev->cipher);
> +                  return err;
> +                }
> +	    }
> +
> +          grub_cryptodisk_insert (dev, diskname, disk);
> +
> +          grub_free (cipher);
> +          grub_free (digest);
> +
> +          err = GRUB_ERR_NONE;
> +        }
> +      else
> +        err = grub_cryptodisk_scan_device_real (args[0], disk);
>  
>        grub_disk_close (disk);
>  
> @@ -1177,13 +1281,203 @@ struct grub_procfs_entry luks_script =
>    .get_contents = luks_script_get
>  };
>  
> +grub_cryptodisk_t
> +grub_cryptodisk_create (grub_disk_t disk, char *uuid,
> +		   char *ciphername, char *ciphermode, char *hashspec)
> +{
> +  grub_cryptodisk_t newdev;
> +  char *cipheriv = NULL;
> +  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
> +  grub_crypto_cipher_handle_t essiv_cipher = NULL;
> +  const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
> +  const struct gcry_cipher_spec *ciph;
> +  grub_cryptodisk_mode_t mode;
> +  grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
> +  int benbi_log = 0;
> +
> +  if (!uuid)
> +    uuid = (char*)"00000000000000000000000000000000";
> +
> +  ciph = grub_crypto_lookup_cipher_by_name (ciphername);
> +  if (!ciph)
> +    {
> +      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
> +		  ciphername);
> +      return NULL;
> +    }
> +
> +  /* Configure the cipher used for the bulk data.  */
> +  cipher = grub_crypto_cipher_open (ciph);
> +  if (!cipher)
> +    return NULL;
> +
> +  /* Configure the cipher mode.  */
> +  if (grub_strcmp (ciphermode, "ecb") == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_ECB;
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> +      cipheriv = NULL;
> +    }
> +  else if (grub_strcmp (ciphermode, "plain") == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_CBC;
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> +      cipheriv = NULL;
> +    }
> +  else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_CBC;
> +      cipheriv = ciphermode + sizeof ("cbc-") - 1;
> +    }
> +  else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_PCBC;
> +      cipheriv = ciphermode + sizeof ("pcbc-") - 1;
> +    }
> +  else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_XTS;
> +      cipheriv = ciphermode + sizeof ("xts-") - 1;
> +      secondary_cipher = grub_crypto_cipher_open (ciph);
> +      if (!secondary_cipher)
> +	{
> +	  grub_crypto_cipher_close (cipher);
> +	  return NULL;
> +	}
> +      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> +	{
> +	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
> +		      cipher->cipher->blocksize);
> +	  grub_crypto_cipher_close (cipher);
> +	  grub_crypto_cipher_close (secondary_cipher);
> +	  return NULL;
> +	}
> +      if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> +	{
> +	  grub_crypto_cipher_close (cipher);
> +	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
> +		      secondary_cipher->cipher->blocksize);
> +	  grub_crypto_cipher_close (secondary_cipher);
> +	  return NULL;
> +	}
> +    }
> +  else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
> +    {
> +      mode = GRUB_CRYPTODISK_MODE_LRW;
> +      cipheriv = ciphermode + sizeof ("lrw-") - 1;
> +      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> +	{
> +	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
> +		      cipher->cipher->blocksize);
> +	  grub_crypto_cipher_close (cipher);
> +	  return NULL;
> +	}
> +    }
> +  else
> +    {
> +      grub_crypto_cipher_close (cipher);
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
> +		  ciphermode);
> +      return NULL;
> +    }
> +
> +  if (cipheriv == NULL);
> +  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> +  else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
> +  else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
> +    {
> +      if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
> +	  || cipher->cipher->blocksize == 0)
> +	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
> +		    cipher->cipher->blocksize);
> +	/* FIXME should we return an error here? */
> +      for (benbi_log = 0;
> +	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
> +	   benbi_log++);
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
> +    }
> +  else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
> +  else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
> +    {
> +      char *hash_str = cipheriv + 6;
> +
> +      mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
> +
> +      /* Configure the hash and cipher used for ESSIV.  */
> +      essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
> +      if (!essiv_hash)
> +	{
> +	  grub_crypto_cipher_close (cipher);
> +	  grub_crypto_cipher_close (secondary_cipher);
> +	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
> +		      "Couldn't load %s hash", hash_str);
> +	  return NULL;
> +	}
> +      essiv_cipher = grub_crypto_cipher_open (ciph);
> +      if (!essiv_cipher)
> +	{
> +	  grub_crypto_cipher_close (cipher);
> +	  grub_crypto_cipher_close (secondary_cipher);
> +	  return NULL;
> +	}
> +    }
> +  else
> +    {
> +      grub_crypto_cipher_close (cipher);
> +      grub_crypto_cipher_close (secondary_cipher);
> +      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
> +		  cipheriv);
> +      return NULL;
> +    }
> +
> +  /* Configure the passphrase hash (LUKS also uses AF splitter and HMAC).  */
> +  hash = grub_crypto_lookup_md_by_name (hashspec);
> +  if (!hash)
> +    {
> +      grub_crypto_cipher_close (cipher);
> +      grub_crypto_cipher_close (essiv_cipher);
> +      grub_crypto_cipher_close (secondary_cipher);
> +      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
> +		  hashspec);
> +      return NULL;
> +    }
> +
> +  newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
> +  if (!newdev)
> +    {
> +      grub_crypto_cipher_close (cipher);
> +      grub_crypto_cipher_close (essiv_cipher);
> +      grub_crypto_cipher_close (secondary_cipher);
> +      return NULL;
> +    }
> +  newdev->cipher = cipher;
> +  newdev->offset = 0;
> +  newdev->source_disk = NULL;
> +  newdev->benbi_log = benbi_log;
> +  newdev->mode = mode;
> +  newdev->mode_iv = mode_iv;
> +  newdev->secondary_cipher = secondary_cipher;
> +  newdev->essiv_cipher = essiv_cipher;
> +  newdev->essiv_hash = essiv_hash;
> +  newdev->hash = hash;
> +  newdev->log_sector_size = 9;
> +  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> +  grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
> +  COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
> +
> +  return newdev;
> +}
> +
>  static grub_extcmd_t cmd;
>  
>  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|-H file"),
> +			      N_("SOURCE|-u UUID|-a|-b|-H file|-p -c cipher -d digest"),
>  			      N_("Mount a crypto device."), options);
>    grub_procfs_register ("luks_script", &luks_script);
>  }
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 11e437e..4ebe21b 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -30,8 +30,6 @@
>  
>  GRUB_MOD_LICENSE ("GPLv3+");
>  
> -#define MAX_PASSPHRASE 256
> -
>  #define LUKS_KEY_ENABLED  0x00AC71F3
>  
>  /* On disk LUKS header */
> @@ -76,15 +74,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    char uuid[sizeof (header.uuid) + 1];
>    char ciphername[sizeof (header.cipherName) + 1];
>    char ciphermode[sizeof (header.cipherMode) + 1];
> -  char *cipheriv = NULL;
>    char hashspec[sizeof (header.hashSpec) + 1];
> -  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
> -  grub_crypto_cipher_handle_t essiv_cipher = NULL;
> -  const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
> -  const struct gcry_cipher_spec *ciph;
> -  grub_cryptodisk_mode_t mode;
> -  grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
> -  int benbi_log = 0;
>    grub_err_t err;
>  
>    err = GRUB_ERR_NONE;
> @@ -119,7 +109,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>         iptr++)
>      {
>        if (*iptr != '-')
> -	*optr++ = *iptr;
> +        *optr++ = *iptr;
>      }
>    *optr = 0;
>  
> @@ -129,6 +119,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>      }
>  
> +
>    /* Make sure that strings are null terminated.  */
>    grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
>    ciphername[sizeof (header.cipherName)] = 0;
> @@ -137,184 +128,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
>    hashspec[sizeof (header.hashSpec)] = 0;
>  
> -  ciph = grub_crypto_lookup_cipher_by_name (ciphername);
> -  if (!ciph)
> -    {
> -      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
> -		  ciphername);
> -      return NULL;
> -    }
> -
> -  /* Configure the cipher used for the bulk data.  */
> -  cipher = grub_crypto_cipher_open (ciph);
> -  if (!cipher)
> -    return NULL;
> -
> -  if (grub_be_to_cpu32 (header.keyBytes) > 1024)
> -    {
> -      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
> -		  grub_be_to_cpu32 (header.keyBytes));
> -      grub_crypto_cipher_close (cipher);
> -      return NULL;
> -    }
> -
> -  /* Configure the cipher mode.  */
> -  if (grub_strcmp (ciphermode, "ecb") == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_ECB;
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> -      cipheriv = NULL;
> -    }
> -  else if (grub_strcmp (ciphermode, "plain") == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_CBC;
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> -      cipheriv = NULL;
> -    }
> -  else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_CBC;
> -      cipheriv = ciphermode + sizeof ("cbc-") - 1;
> -    }
> -  else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_PCBC;
> -      cipheriv = ciphermode + sizeof ("pcbc-") - 1;
> -    }
> -  else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_XTS;
> -      cipheriv = ciphermode + sizeof ("xts-") - 1;
> -      secondary_cipher = grub_crypto_cipher_open (ciph);
> -      if (!secondary_cipher)
> -	{
> -	  grub_crypto_cipher_close (cipher);
> -	  return NULL;
> -	}
> -      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> -	{
> -	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
> -		      cipher->cipher->blocksize);
> -	  grub_crypto_cipher_close (cipher);
> -	  grub_crypto_cipher_close (secondary_cipher);
> -	  return NULL;
> -	}
> -      if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> -	{
> -	  grub_crypto_cipher_close (cipher);
> -	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
> -		      secondary_cipher->cipher->blocksize);
> -	  grub_crypto_cipher_close (secondary_cipher);
> -	  return NULL;
> -	}
> -    }
> -  else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
> -    {
> -      mode = GRUB_CRYPTODISK_MODE_LRW;
> -      cipheriv = ciphermode + sizeof ("lrw-") - 1;
> -      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
> -	{
> -	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
> -		      cipher->cipher->blocksize);
> -	  grub_crypto_cipher_close (cipher);
> -	  return NULL;
> -	}
> -    }
> -  else
> -    {
> -      grub_crypto_cipher_close (cipher);
> -      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
> -		  ciphermode);
> -      return NULL;
> -    }
> -
> -  if (cipheriv == NULL);
> -  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
> -  else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
> -  else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
> -    {
> -      if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
> -	  || cipher->cipher->blocksize == 0)
> -	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
> -		    cipher->cipher->blocksize);
> -	/* FIXME should we return an error here? */
> -      for (benbi_log = 0; 
> -	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
> -	   benbi_log++);
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
> -    }
> -  else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
> -  else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
> -    {
> -      char *hash_str = cipheriv + 6;
> -
> -      mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
> -
> -      /* Configure the hash and cipher used for ESSIV.  */
> -      essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
> -      if (!essiv_hash)
> -	{
> -	  grub_crypto_cipher_close (cipher);
> -	  grub_crypto_cipher_close (secondary_cipher);
> -	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
> -		      "Couldn't load %s hash", hash_str);
> -	  return NULL;
> -	}
> -      essiv_cipher = grub_crypto_cipher_open (ciph);
> -      if (!essiv_cipher)
> -	{
> -	  grub_crypto_cipher_close (cipher);
> -	  grub_crypto_cipher_close (secondary_cipher);
> -	  return NULL;
> -	}
> -    }
> -  else
> -    {
> -      grub_crypto_cipher_close (cipher);
> -      grub_crypto_cipher_close (secondary_cipher);
> -      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
> -		  cipheriv);
> -      return NULL;
> -    }
> -
> -  /* Configure the hash used for the AF splitter and HMAC.  */
> -  hash = grub_crypto_lookup_md_by_name (hashspec);
> -  if (!hash)
> -    {
> -      grub_crypto_cipher_close (cipher);
> -      grub_crypto_cipher_close (essiv_cipher);
> -      grub_crypto_cipher_close (secondary_cipher);
> -      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
> -		  hashspec);
> -      return NULL;
> -    }
> +  newdev = grub_cryptodisk_create (disk, uuid, ciphername, ciphermode, hashspec);
>  
> -  newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
> -  if (!newdev)
> -    {
> -      grub_crypto_cipher_close (cipher);
> -      grub_crypto_cipher_close (essiv_cipher);
> -      grub_crypto_cipher_close (secondary_cipher);
> -      return NULL;
> -    }
> -  newdev->cipher = cipher;
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> -  newdev->source_disk = NULL;
> -  newdev->benbi_log = benbi_log;
> -  newdev->mode = mode;
> -  newdev->mode_iv = mode_iv;
> -  newdev->secondary_cipher = secondary_cipher;
> -  newdev->essiv_cipher = essiv_cipher;
> -  newdev->essiv_hash = essiv_hash;
> -  newdev->hash = hash;
> -  newdev->log_sector_size = 9;
> -  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> -  grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
>    newdev->modname = "luks";
> -  COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
>  
>    return newdev;
>  }
> @@ -329,7 +146,7 @@ luks_recover_key (grub_disk_t source,
>    struct grub_luks_phdr header;
>    grub_size_t keysize;
>    grub_uint8_t *split_key = NULL;
> -  char interactive_passphrase[MAX_PASSPHRASE] = "";
> +  char interactive_passphrase[GRUB_CRYPTODISK_MAX_PASSPHRASE] = "";
>    grub_uint8_t *passphrase;
>    grub_size_t passphrase_length;
>    grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
> @@ -376,7 +193,7 @@ luks_recover_key (grub_disk_t source,
>            /* Use bytestring from key file as passphrase */
>            passphrase = keyfile_bytes;
>            passphrase_length = keyfile_bytes_size;
> -	  keyfile_bytes = NULL; /* use it only once */
> +          keyfile_bytes = NULL; /* use it only once */
>          }
>        else
>          {
> @@ -387,7 +204,7 @@ luks_recover_key (grub_disk_t source,
>            grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
>                                source->partition ? "," : "", tmp ? : "", dev->uuid);
>            grub_free (tmp);
> -          if (!grub_password_get (interactive_passphrase, MAX_PASSPHRASE))
> +          if (!grub_password_get (interactive_passphrase, GRUB_CRYPTODISK_MAX_PASSPHRASE))
>              {
>                grub_free (split_key);
>                return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 0299625..4076412 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -54,9 +54,14 @@ typedef enum
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
>  #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
>  #define GRUB_CRYPTODISK_MAX_KEYLEN 128
> +#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
>  
>  #define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192
>  
> +#define GRUB_CRYPTODISK_PLAIN_CIPHER  "aes-cbc-essiv:sha256"
> +#define GRUB_CRYPTODISK_PLAIN_DIGEST  "ripemd160"
> +#define GRUB_CRYPTODISK_PLAIN_KEYSIZE 256
> +
>  struct grub_cryptodisk;
>  
>  typedef gcry_err_code_t
> @@ -159,4 +164,7 @@ grub_util_get_geli_uuid (const char *dev);
>  grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
>  grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
>  
> +grub_cryptodisk_t grub_cryptodisk_create (grub_disk_t disk, char *uuid,
> +				   char *ciphername, char *ciphermode, char *digest);
> +
>  #endif
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-02-12 15:20 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-29 14:30 Cryptomount enhancements - revised John Lane
2015-06-29 14:30 ` [PATCH 1/5] Cryptomount support LUKS detached header John Lane
2015-06-29 14:30 ` [PATCH 2/5] Cryptomount support key files John Lane
2015-06-29 14:30 ` [PATCH 3/5] cryptomount luks allow multiple passphrase attempts John Lane
2015-06-29 14:56   ` John Lane
2015-06-29 14:30 ` [PATCH 4/5] Cryptomount support plain dm-crypt John Lane
2016-02-12 15:19   ` Vladimir 'φ-coder/phcoder' Serbinenko
2015-06-29 14:31 ` [PATCH 5/5] Cryptomount support for hyphens in UUID John Lane
2015-06-29 14:52   ` John Lane
2015-07-29  3:08   ` Andrei Borzenkov
2015-07-29  6:51     ` John Lane
2015-07-29 16:51       ` Andrei Borzenkov
2015-07-29 18:53         ` John Lane
2015-07-28 18:51 ` Cryptomount enhancements - revised John Lane
2015-07-28 21:38   ` Vladimir 'phcoder' Serbinenko
2015-07-29  6:48     ` John Lane
2015-07-29 17:21       ` Andrei Borzenkov
2015-08-01 16:22         ` John Lane

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.