]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Integrate geli into autoconfiguration system
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 25 Apr 2011 12:52:07 +0000 (14:52 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 25 Apr 2011 12:52:07 +0000 (14:52 +0200)
13 files changed:
grub-core/disk/cryptodisk.c
grub-core/disk/geli.c
grub-core/disk/luks.c
grub-core/kern/emu/getroot.c
grub-core/kern/emu/hostdisk.c
include/grub/cryptodisk.h
include/grub/emu/getroot.h
include/grub/emu/hostdisk.h
util/grub-fstest.c
util/grub-install.in
util/grub-mkconfig.in
util/grub-mkconfig_lib.in
util/grub-probe.c

index bf0b1cde2b53046c47750bebed146e2466589b28..1a5e8164bcbc7ff62e502eafc7082cd25e4c00aa 100644 (file)
@@ -20,6 +20,8 @@
 #include <grub/mm.h>
 #include <grub/misc.h>
 #include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/i18n.h>
 
 #ifdef GRUB_UTIL
 #include <errno.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+grub_cryptodisk_dev_t grub_cryptodisk_list;
+
+static const struct grub_arg_option options[] =
+  {
+    {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
+    {"all", 'a', 0, N_("Mount all."), 0, 0},
+    {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
+    {0, 0, 0, 0, 0, 0}
+  };
+
 /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is:  */
 #define GF_POLYNOM 0x87
 static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev)
@@ -480,7 +492,7 @@ grub_cryptodisk_close (grub_disk_t disk)
 
 static grub_err_t
 grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
-               grub_size_t size, char *buf)
+                     grub_size_t size, char *buf)
 {
   grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
   grub_err_t err;
@@ -635,7 +647,7 @@ grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
 {
   grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
 
-  grub_printf ("luks ");
+  grub_printf ("cryptodisk %s ", dev->modname);
 
   if (dev->cipher)
     grub_printf ("%s ", dev->cipher->cipher->modname);
@@ -650,8 +662,197 @@ grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
   if (dev->iv_hash)
     grub_printf ("%s ", dev->iv_hash->modname);
 }
+
+void
+grub_util_cryptodisk_print_uuid (grub_disk_t disk)
+{
+  grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
+  grub_printf ("%s ", dev->uuid);
+}
+
 #endif
 
+static int check_boot, have_it;
+static char *search_uuid;
+
+static void
+cryptodisk_close (grub_cryptodisk_t dev)
+{
+  grub_crypto_cipher_close (dev->cipher);
+  grub_crypto_cipher_close (dev->secondary_cipher);
+  grub_crypto_cipher_close (dev->essiv_cipher);
+  grub_free (dev);
+}
+
+static grub_err_t
+grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
+{
+  grub_err_t err;
+  grub_cryptodisk_t dev;
+  grub_cryptodisk_dev_t cr;
+
+  dev = grub_cryptodisk_get_by_source_disk (source);
+
+  if (dev)
+    return GRUB_ERR_NONE;
+
+  FOR_CRYPTODISK_DEVS (cr)
+  {
+    dev = cr->scan (source, search_uuid, check_boot);
+    if (grub_errno)
+      return grub_errno;
+    if (!dev)
+      continue;
+    
+    err = cr->recover_key (source, dev);
+    if (err)
+    {
+      cryptodisk_close (dev);
+      return err;
+    }
+
+    grub_cryptodisk_insert (dev, name, source);
+
+    have_it = 1;
+
+    return GRUB_ERR_NONE;
+  }
+  return GRUB_ERR_NONE;
+}
+
+#ifdef GRUB_UTIL
+#include <grub/util/misc.h>
+grub_err_t
+grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
+{
+  grub_err_t err;
+  grub_cryptodisk_t dev;
+  grub_cryptodisk_dev_t cr;
+  grub_disk_t source;
+
+  /* Try to open disk.  */
+  source = grub_disk_open (sourcedev);
+  if (!source)
+    return grub_errno;
+
+  dev = grub_cryptodisk_get_by_source_disk (source);
+
+  if (dev)
+    {
+      grub_disk_close (source);        
+      return GRUB_ERR_NONE;
+    }
+
+  FOR_CRYPTODISK_DEVS (cr)
+  {
+    dev = cr->scan (source, search_uuid, check_boot);
+    if (grub_errno)
+      return grub_errno;
+    if (!dev)
+      continue;
+
+    grub_util_info ("cheatmounted %s (%s) at %s", sourcedev, dev->modname,
+                   cheat);
+    err = grub_cryptodisk_cheat_insert (dev, sourcedev, source, cheat);
+    grub_disk_close (source);
+    if (err)
+      grub_free (dev);
+
+    return GRUB_ERR_NONE;
+  }
+
+  grub_disk_close (source);
+
+  return GRUB_ERR_NONE;
+}
+#endif
+
+static int
+grub_cryptodisk_scan_device (const char *name)
+{
+  grub_err_t err;
+  grub_disk_t source;
+
+  /* Try to open disk.  */
+  source = grub_disk_open (name);
+  if (!source)
+    return grub_errno;
+
+  err = grub_cryptodisk_scan_device_real (name, source);
+
+  grub_disk_close (source);
+  
+  if (err)
+    grub_print_error ();
+  return have_it && search_uuid ? 1 : 0;
+}
+
+static grub_err_t
+grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  struct grub_arg_list *state = ctxt->state;
+
+  if (argc < 1 && !state[1].set && !state[2].set)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+
+  have_it = 0;
+  if (state[0].set)
+    {
+      grub_cryptodisk_t dev;
+
+      dev = grub_cryptodisk_get_by_uuid (args[0]);
+      if (dev)
+       {
+         grub_dprintf ("cryptodisk",
+                       "already mounted as crypto%lu\n", dev->id);
+         return GRUB_ERR_NONE;
+       }
+
+      check_boot = state[2].set;
+      search_uuid = args[0];
+      grub_device_iterate (&grub_cryptodisk_scan_device);
+      search_uuid = NULL;
+
+      if (!have_it)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+      return GRUB_ERR_NONE;
+    }
+  else if (state[1].set || (argc == 0 && state[2].set))
+    {
+      search_uuid = NULL;
+      check_boot = state[2].set;
+      grub_device_iterate (&grub_cryptodisk_scan_device);
+      search_uuid = NULL;
+      return GRUB_ERR_NONE;
+    }
+  else
+    {
+      grub_err_t err;
+      grub_disk_t disk;
+      grub_cryptodisk_t dev;
+
+      search_uuid = NULL;
+      check_boot = state[2].set;
+      disk = grub_disk_open (args[0]);
+      if (!disk)
+       return grub_errno;
+
+      dev = grub_cryptodisk_get_by_source_disk (disk);
+      if (dev)
+       {
+         grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
+         grub_disk_close (disk);
+         return GRUB_ERR_NONE;
+       }
+
+      err = grub_cryptodisk_scan_device_real (args[0], disk);
+
+      grub_disk_close (disk);
+
+      return err;
+    }
+}
+
 static struct grub_disk_dev grub_cryptodisk_dev = {
   .name = "cryptodisk",
   .id = GRUB_DISK_DEVICE_CRYPTODISK_ID,
@@ -666,9 +867,14 @@ static struct grub_disk_dev grub_cryptodisk_dev = {
   .next = 0
 };
 
+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"),
+                             N_("Mount a crypto device."), options);
 }
 
 GRUB_MOD_FINI (cryptodisk)
index 1353be172486853580794b0c695265e2d7c0cf7b..d2ae5da56feb93ed2fb46d540f967addab9d79ff 100644 (file)
@@ -53,7 +53,7 @@
 #include <grub/err.h>
 #include <grub/disk.h>
 #include <grub/crypto.h>
-#include <grub/extcmd.h>
+#include <grub/partition.h>
 #include <grub/i18n.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -105,17 +105,6 @@ const char *algorithms[] = {
 
 #define MAX_PASSPHRASE 256
 
-static const struct grub_arg_option options[] =
-  {
-    {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
-    {"all", 'a', 0, N_("Mount all."), 0, 0},
-    {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
-    {0, 0, 0, 0, 0, 0}
-  };
-
-static int check_uuid, check_boot, have_it;
-static char *search_uuid;
-
 static gcry_err_code_t
 geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
 {
@@ -150,79 +139,155 @@ ascii2hex (char c)
   return 0;
 }
 
-static grub_cryptodisk_t
-configure_ciphers (const struct grub_geli_phdr *header)
+static inline gcry_err_code_t
+make_uuid (const struct grub_geli_phdr *header,
+          char *uuid)
 {
-  grub_cryptodisk_t newdev;
-  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
-  const struct gcry_cipher_spec *ciph;
-  const char *ciphername = NULL;
-  char uuid[GRUB_MD_SHA256->mdlen * 2 + 1];
   grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen];
+  gcry_err_code_t err;
   grub_uint8_t *iptr;
   char *optr;
-  gcry_err_code_t gcry_err;
+
+  err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
+                                header->salt, sizeof (header->salt),
+                                "uuid", sizeof ("uuid") - 1, uuidbin);
+  if (err)
+    return err;
+
+  optr = uuid;
+  for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++)
+    {
+      grub_snprintf (optr, 3, "%02x", *iptr);
+      optr += 2;
+    }
+  *optr = 0;
+  return GPG_ERR_NO_ERROR;
+}
+
+#ifdef GRUB_UTIL
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <grub/emu/hostdisk.h>
+#include <unistd.h>
+#include <string.h>
+#include <grub/emu/misc.h>
+
+char *
+grub_util_get_geli_uuid (const char *dev)
+{
+  int fd = open (dev, O_RDONLY);
+  grub_uint64_t s;
+  unsigned log_secsize;
+  grub_uint8_t hdr[512];
+  struct grub_geli_phdr *header;
+  char *uuid; 
+  gcry_err_code_t err;
+
+  if (fd < 0)
+    return NULL;
+
+  s = grub_util_get_fd_sectors (fd, &log_secsize);
+  grub_util_fd_seek (fd, dev, (s << log_secsize) - 512);
+
+  uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
+  if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
+    grub_util_error ("couldn't read ELI metadata");
+         
+  COMPILE_TIME_ASSERT (sizeof (header) <= 512);
+  header = (void *) &hdr;
 
   /* Look for GELI magic sequence.  */
   if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
       || grub_le_to_cpu32 (header->version) > 5
       || grub_le_to_cpu32 (header->version) < 1)
+    grub_util_error ("wrong ELI magic or version");
+
+  err = make_uuid ((void *) &hdr, uuid);
+  if (err)
+    return NULL;
+
+  return uuid;
+}
+#endif
+
+static grub_cryptodisk_t
+configure_ciphers (grub_disk_t disk, const char *check_uuid,
+                  int boot_only)
+{
+  grub_cryptodisk_t newdev;
+  struct grub_geli_phdr header;
+  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
+  const struct gcry_cipher_spec *ciph;
+  const char *ciphername = NULL;
+  gcry_err_code_t gcry_err;
+  char uuid[GRUB_MD_SHA256->mdlen * 2 + 1];
+  grub_disk_addr_t sector;
+  grub_err_t err;
+
+  sector = grub_disk_get_size (disk);
+  if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
+    return NULL;
+
+  /* Read the GELI header.  */
+  err = grub_disk_read (disk, sector - 1, 0, sizeof (header), &header);
+  if (err)
+    return NULL;
+
+  /* Look for GELI magic sequence.  */
+  if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
+      || grub_le_to_cpu32 (header.version) > 5
+      || grub_le_to_cpu32 (header.version) < 1)
     {
-      grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]);
+      grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
       return NULL;
     }
-  if ((grub_le_to_cpu32 (header->sector_size)
-       & (grub_le_to_cpu32 (header->sector_size) - 1))
-      || grub_le_to_cpu32 (header->sector_size) == 0)
+
+  if ((grub_le_to_cpu32 (header.sector_size)
+       & (grub_le_to_cpu32 (header.sector_size) - 1))
+      || grub_le_to_cpu32 (header.sector_size) == 0)
     {
       grub_dprintf ("geli", "incorrect sector size %d\n",
-                   grub_le_to_cpu32 (header->sector_size));
+                   grub_le_to_cpu32 (header.sector_size));
       return NULL;
     }
 
-  if (grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_ONETIME)
+  if (grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_ONETIME)
     {
       grub_dprintf ("geli", "skipping one-time volume\n");
       return NULL;
     }
 
-  if (check_boot && !(grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_BOOT))
+  if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
     {
       grub_dprintf ("geli", "not a boot volume\n");
       return NULL;
     }    
 
-  gcry_err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
-                                     header->salt, sizeof (header->salt),
-                                     "uuid", sizeof ("uuid") - 1, uuidbin);
+  gcry_err = make_uuid (&header, uuid);
   if (gcry_err)
     {
       grub_crypto_gcry_error (gcry_err);
       return NULL;
     }
-  optr = uuid;
-  for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++)
-    {
-      grub_snprintf (optr, 3, "%02x", *iptr);
-      optr += 2;
-    }
-  *optr = 0;
 
-  if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0)
+  if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
     {
-      grub_dprintf ("geli", "%s != %s\n", uuid, search_uuid);
+      grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
       return NULL;
     }
 
-  if (grub_le_to_cpu16 (header->alg) >= ARRAY_SIZE (algorithms)
-      || algorithms[grub_le_to_cpu16 (header->alg)] == NULL)
+  if (grub_le_to_cpu16 (header.alg) >= ARRAY_SIZE (algorithms)
+      || algorithms[grub_le_to_cpu16 (header.alg)] == NULL)
     {
       grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown",
-                 grub_le_to_cpu16 (header->alg));
+                 grub_le_to_cpu16 (header.alg));
       return NULL;
     }
 
-  ciphername = algorithms[grub_le_to_cpu16 (header->alg)];
+  ciphername = algorithms[grub_le_to_cpu16 (header.alg)];
   ciph = grub_crypto_lookup_cipher_by_name (ciphername);
   if (!ciph)
     {
@@ -236,17 +301,17 @@ configure_ciphers (const struct grub_geli_phdr *header)
   if (!cipher)
     return NULL;
 
-  if (grub_le_to_cpu16 (header->alg) == 0x16)
+  if (grub_le_to_cpu16 (header.alg) == 0x16)
     {
       secondary_cipher = grub_crypto_cipher_open (ciph);
       if (!secondary_cipher)
        return NULL;
     }
 
-  if (grub_le_to_cpu16 (header->keylen) > 1024)
+  if (grub_le_to_cpu16 (header.keylen) > 1024)
     {
       grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
-                 grub_le_to_cpu16 (header->keylen));
+                 grub_le_to_cpu16 (header.keylen));
       return NULL;
     }
 
@@ -258,7 +323,7 @@ configure_ciphers (const struct grub_geli_phdr *header)
   newdev->offset = 0;
   newdev->source_disk = NULL;
   newdev->benbi_log = 0;
-  if (grub_le_to_cpu16 (header->alg) == 0x16)
+  if (grub_le_to_cpu16 (header.alg) == 0x16)
     {
       newdev->mode = GRUB_CRYPTODISK_MODE_XTS;
       newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64;
@@ -274,25 +339,29 @@ configure_ciphers (const struct grub_geli_phdr *header)
   newdev->iv_hash = GRUB_MD_SHA256;
 
   for (newdev->log_sector_size = 0;
-       (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header->sector_size);
+       (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header.sector_size);
        newdev->log_sector_size++);
 
-  if (grub_le_to_cpu32 (header->version) >= 5)
+  if (grub_le_to_cpu32 (header.version) >= 5)
     {
       newdev->rekey = geli_rekey;
       newdev->rekey_shift = 20;
     }
 
+#ifdef GRUB_UTIL
+  newdev->modname = "geli";
+#endif
+
+  newdev->total_length = grub_disk_get_size (disk) - 1;
   grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
   COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
   return newdev;
 }
 
 static grub_err_t
-recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
-            const char *name, grub_disk_t source __attribute__ ((unused)))
+recover_key (grub_disk_t source, grub_cryptodisk_t dev)
 {
-  grub_size_t keysize = grub_le_to_cpu16 (header->keylen) / 8;
+  grub_size_t keysize;
   grub_uint8_t digest[dev->hash->mdlen];
   grub_uint8_t geomkey[dev->hash->mdlen];
   grub_uint8_t verify_key[dev->hash->mdlen];
@@ -300,25 +369,45 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
   char passphrase[MAX_PASSPHRASE] = "";
   unsigned i;
   gcry_err_code_t gcry_err;
+  struct grub_geli_phdr header;
+  char *tmp;
+  grub_disk_addr_t sector;
+  grub_err_t err;
+
+  sector = grub_disk_get_size (source);
+  if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
+    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
 
+  /* Read the GELI header.  */
+  err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
+  if (err)
+    return err;
+
+  keysize = grub_le_to_cpu16 (header.keylen) / 8;
   grub_memset (zero, 0, sizeof (zero));
 
   grub_printf ("Attempting to decrypt master key...\n");
 
   /* Get the passphrase from the user.  */
-  grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid);
+  tmp = NULL;
+  if (source->partition)
+    tmp = grub_partition_get_name (source->partition);
+  grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
+              source->partition ? "," : "", tmp ? : "",
+              dev->uuid);
+  grub_free (tmp);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
 
   /* Calculate the PBKDF2 of the user supplied passphrase.  */
-  if (grub_le_to_cpu32 (header->niter) != 0)
+  if (grub_le_to_cpu32 (header.niter) != 0)
     {
       grub_uint8_t pbkdf_key[64];
       gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
                                     grub_strlen (passphrase),
-                                    header->salt,
-                                    sizeof (header->salt),
-                                    grub_le_to_cpu32 (header->niter),
+                                    header.salt,
+                                    sizeof (header.salt),
+                                    grub_le_to_cpu32 (header.niter),
                                     pbkdf_key, sizeof (pbkdf_key));
 
       if (gcry_err)
@@ -337,7 +426,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
       if (!hnd)
        return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
 
-      grub_crypto_hmac_write (hnd, header->salt, sizeof (header->salt));
+      grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
       grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
 
       gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
@@ -358,13 +447,13 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
   grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize);
 
   /* Try to recover master key from each active keyslot.  */
-  for (i = 0; i < ARRAY_SIZE (header->keys); i++)
+  for (i = 0; i < ARRAY_SIZE (header.keys); i++)
     {
       struct grub_geli_key candidate_key;
       grub_uint8_t key_hmac[dev->hash->mdlen];
 
       /* Check if keyslot is enabled.  */
-      if (! (header->keys_used & (1 << i)))
+      if (! (header.keys_used & (1 << i)))
          continue;
 
       grub_dprintf ("geli", "Trying keyslot %d\n", i);
@@ -375,7 +464,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
        return grub_crypto_gcry_error (gcry_err);
 
       gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key,
-                                         &header->keys[i],
+                                         &header.keys[i],
                                          sizeof (candidate_key),
                                          zero);
       if (gcry_err)
@@ -398,7 +487,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
       if (!dev->rekey)
        {
          grub_size_t real_keysize = keysize;
-         if (grub_le_to_cpu16 (header->alg) == 0x16)
+         if (grub_le_to_cpu16 (header.alg) == 0x16)
            real_keysize *= 2;
          gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key,
                                             real_keysize); 
@@ -408,7 +497,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
       else
        {
          grub_size_t real_keysize = keysize;
-         if (grub_le_to_cpu16 (header->alg) == 0x16)
+         if (grub_le_to_cpu16 (header.alg) == 0x16)
            real_keysize *= 2;
          /* For a reason I don't know, the IV key is used in rekeying.  */
          grub_memcpy (dev->rekey_key, candidate_key.iv_key,
@@ -431,216 +520,17 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header,
   return GRUB_ACCESS_DENIED;
 }
 
-static void
-close (grub_cryptodisk_t luks)
-{
-  grub_crypto_cipher_close (luks->cipher);
-  grub_crypto_cipher_close (luks->secondary_cipher);
-  grub_crypto_cipher_close (luks->essiv_cipher);
-  grub_free (luks);
-}
-
-static grub_err_t
-grub_geli_scan_device_real (const char *name, grub_disk_t source)
-{
-  grub_err_t err;
-  struct grub_geli_phdr header;
-  grub_cryptodisk_t newdev, dev;
-  grub_disk_addr_t sector;
-
-  grub_dprintf ("geli", "scanning %s\n", source->name);
-  dev = grub_cryptodisk_get_by_source_disk (source);
-
-  if (dev)
-    return GRUB_ERR_NONE;
-
-  sector = grub_disk_get_size (source);
-  if (sector == GRUB_DISK_SIZE_UNKNOWN)
-    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
-
-  /* Read the LUKS header.  */
-  err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
-  if (err)
-    return err;
-
-  newdev = configure_ciphers (&header);
-  if (!newdev)
-    return grub_errno;
-
-  newdev->total_length = grub_disk_get_size (source) - 1;
-
-  err = recover_key (newdev, &header, name, source);
-  if (err)
-    {
-      close (newdev);
-      return err;
-    }
-
-  grub_cryptodisk_insert (newdev, name, source);
-
-  have_it = 1;
-
-  return GRUB_ERR_NONE;
-}
-
-#ifdef GRUB_UTIL
-grub_err_t
-grub_geli_cheat_mount (const char *sourcedev, const char *cheat)
-{
-  grub_err_t err;
-  struct grub_geli_phdr header;
-  grub_cryptodisk_t newdev, dev;
-  grub_disk_t source;
-  grub_disk_addr_t sector;
-
-  /* Try to open disk.  */
-  source = grub_disk_open (sourcedev);
-  if (!source)
-    return grub_errno;
-
-  dev = grub_cryptodisk_get_by_source_disk (source);
-
-  if (dev)
-    {
-      grub_disk_close (source);        
-      return GRUB_ERR_NONE;
-    }
-
-  sector = grub_disk_get_size (source);
-  if (sector == GRUB_DISK_SIZE_UNKNOWN)
-    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
-
-  /* Read the LUKS header.  */
-  err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
-  if (err)
-    return err;
-
-  newdev = configure_ciphers (&header);
-  if (!newdev)
-    {
-      grub_disk_close (source);
-      return grub_errno;
-    }
-
-  newdev->total_length = grub_disk_get_size (source) - 1;
-
-  err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat);
-  grub_disk_close (source);
-  if (err)
-    grub_free (newdev);
-
-  return err;
-}
-#endif
-
-static int
-grub_geli_scan_device (const char *name)
-{
-  grub_err_t err;
-  grub_disk_t source;
-
-  /* Try to open disk.  */
-  source = grub_disk_open (name);
-  if (!source)
-    return grub_errno;
-
-  err = grub_geli_scan_device_real (name, source);
-
-  grub_disk_close (source);
-  
-  if (err)
-    grub_print_error ();
-  return have_it && check_uuid ? 0 : 1;
-}
-
-#ifdef GRUB_UTIL
-
-void
-grub_util_geli_print_uuid (grub_disk_t disk)
-{
-  grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
-  grub_printf ("%s ", dev->uuid);
-}
-#endif
-
-static grub_err_t
-grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args)
-{
-  struct grub_arg_list *state = ctxt->state;
-
-  if (argc < 1 && !state[1].set && !state[2].set)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
-
-  have_it = 0;
-  if (state[0].set)
-    {
-      grub_cryptodisk_t dev;
-
-      dev = grub_cryptodisk_get_by_uuid (args[0]);
-      if (dev)
-       {
-         grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id);
-         return GRUB_ERR_NONE;
-       }
-
-      check_uuid = 1;
-      check_boot = state[2].set;
-      search_uuid = args[0];
-      grub_device_iterate (&grub_geli_scan_device);
-      search_uuid = NULL;
-
-      if (!have_it)
-       return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found");
-      return GRUB_ERR_NONE;
-    }
-  else if (state[1].set || (argc == 0 && state[2].set))
-    {
-      check_uuid = 0;
-      search_uuid = NULL;
-      check_boot = state[2].set;
-      grub_device_iterate (&grub_geli_scan_device);
-      search_uuid = NULL;
-      return GRUB_ERR_NONE;
-    }
-  else
-    {
-      grub_err_t err;
-      grub_disk_t disk;
-      grub_cryptodisk_t dev;
-
-      check_uuid = 0;
-      search_uuid = NULL;
-      check_boot = state[2].set;
-      disk = grub_disk_open (args[0]);
-      if (!disk)
-       return grub_errno;
-
-      dev = grub_cryptodisk_get_by_source_disk (disk);
-      if (dev)
-       {
-         grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id);
-         grub_disk_close (disk);
-         return GRUB_ERR_NONE;
-       }
-
-      err = grub_geli_scan_device_real (args[0], disk);
-
-      grub_disk_close (disk);
-
-      return err;
-    }
-}
-
-static grub_extcmd_t cmd;
+struct grub_cryptodisk_dev geli_crypto = {
+  .scan = configure_ciphers,
+  .recover_key = recover_key
+};
 
 GRUB_MOD_INIT (geli)
 {
-  cmd = grub_register_extcmd ("gelimount", grub_cmd_gelimount, 0,
-                             N_("SOURCE|-u UUID|-a|-b"),
-                             N_("Mount a GELI device."), options);
+  grub_cryptodisk_dev_register (&geli_crypto);
 }
 
 GRUB_MOD_FINI (geli)
 {
-  grub_unregister_extcmd (cmd);
+  grub_cryptodisk_dev_unregister (&geli_crypto);
 }
index aa23e2e359e68751e3dd49ea94a6a6b9dbebb851..0ec95fccdfde727073142b97558cb708d7e8eec2 100644 (file)
@@ -24,7 +24,7 @@
 #include <grub/err.h>
 #include <grub/disk.h>
 #include <grub/crypto.h>
-#include <grub/extcmd.h>
+#include <grub/partition.h>
 #include <grub/i18n.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -64,27 +64,19 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
                          grub_uint8_t * dst, grub_size_t blocksize,
                          grub_size_t blocknumbers);
 
-static const struct grub_arg_option options[] =
-  {
-    {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
-    {"all", 'a', 0, N_("Mount all."), 0, 0},
-    {0, 0, 0, 0, 0, 0}
-  };
-
-static int check_uuid, have_it;
-static char *search_uuid;
-
 static grub_cryptodisk_t
-configure_ciphers (const struct grub_luks_phdr *header)
+configure_ciphers (grub_disk_t disk, const char *check_uuid,
+                  int check_boot)
 {
   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];
+  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];
+  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;
@@ -92,14 +84,27 @@ configure_ciphers (const struct grub_luks_phdr *header)
   grub_cryptodisk_mode_t mode;
   grub_cryptodisk_mode_iv_t mode_iv;
   int benbi_log = 0;
+  grub_err_t err;
+
+  if (check_boot)
+    return NULL;
+
+  /* Read the LUKS header.  */
+  err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
+  if (err)
+    {
+      if (err == GRUB_ERR_OUT_OF_RANGE)
+       grub_errno = GRUB_ERR_NONE;
+      return NULL;
+    }
 
   /* Look for LUKS magic sequence.  */
-  if (grub_memcmp (header->magic, LUKS_MAGIC, sizeof (header->magic))
-      || grub_be_to_cpu16 (header->version) != 1)
+  if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic))
+      || grub_be_to_cpu16 (header.version) != 1)
     return NULL;
 
   optr = uuid;
-  for (iptr = header->uuid; iptr < &header->uuid[ARRAY_SIZE (header->uuid)];
+  for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
        iptr++)
     {
       if (*iptr != '-')
@@ -107,19 +112,19 @@ configure_ciphers (const struct grub_luks_phdr *header)
     }
   *optr = 0;
 
-  if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0)
+  if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
     {
-      grub_dprintf ("luks", "%s != %s\n", uuid, search_uuid);
+      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;
-  grub_memcpy (ciphermode, header->cipherMode, sizeof (header->cipherMode));
-  ciphermode[sizeof (header->cipherMode)] = 0;
-  grub_memcpy (hashspec, header->hashSpec, sizeof (header->hashSpec));
-  hashspec[sizeof (header->hashSpec)] = 0;
+  grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
+  ciphername[sizeof (header.cipherName)] = 0;
+  grub_memcpy (ciphermode, header.cipherMode, sizeof (header.cipherMode));
+  ciphermode[sizeof (header.cipherMode)] = 0;
+  grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
+  hashspec[sizeof (header.hashSpec)] = 0;
 
   ciph = grub_crypto_lookup_cipher_by_name (ciphername);
   if (!ciph)
@@ -134,10 +139,10 @@ configure_ciphers (const struct grub_luks_phdr *header)
   if (!cipher)
     return NULL;
 
-  if (grub_be_to_cpu32 (header->keyBytes) > 1024)
+  if (grub_be_to_cpu32 (header.keyBytes) > 1024)
     {
       grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
-                 grub_be_to_cpu32 (header->keyBytes));
+                 grub_be_to_cpu32 (header.keyBytes));
       return NULL;
     }
 
@@ -273,7 +278,7 @@ configure_ciphers (const struct grub_luks_phdr *header)
   if (!newdev)
     return NULL;
   newdev->cipher = cipher;
-  newdev->offset = grub_be_to_cpu32 (header->payloadOffset);
+  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->benbi_log = benbi_log;
   newdev->mode = mode;
@@ -283,39 +288,54 @@ configure_ciphers (const struct grub_luks_phdr *header)
   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));
+#ifdef GRUB_UTIL
+  newdev->modname = "luks";
+#endif
   COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
   return newdev;
 }
 
 static grub_err_t
-luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
-                 const char *name, grub_disk_t source)
+luks_recover_key (grub_disk_t source,
+                 grub_cryptodisk_t dev)
 {
-  grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes);
-  grub_uint8_t candidate_key[keysize];
-  grub_uint8_t digest[keysize];
+  struct grub_luks_phdr header;
+  grub_size_t keysize;
   grub_uint8_t *split_key = NULL;
   char passphrase[MAX_PASSPHRASE] = "";
-  grub_uint8_t candidate_digest[sizeof (header->mkDigest)];
+  grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
   unsigned i;
   grub_size_t length;
   grub_err_t err;
   grub_size_t max_stripes = 1;
+  char *tmp;
+
+  err = grub_disk_read (source, 0, 0, sizeof (header), &header);
+  if (err)
+    return err;
 
   grub_printf ("Attempting to decrypt master key...\n");
+  keysize = grub_be_to_cpu32 (header.keyBytes);
 
-  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)
-      max_stripes = grub_be_to_cpu32 (header->keyblock[i].stripes);
+  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)
+      max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
 
   split_key = grub_malloc (keysize * max_stripes);
   if (!split_key)
     return grub_errno;
 
   /* Get the passphrase from the user.  */
-  grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid);
+  tmp = NULL;
+  if (source->partition)
+    tmp = grub_partition_get_name (source->partition);
+  grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
+              source->partition ? "," : "", tmp ? : "",
+              dev->uuid);
+  grub_free (tmp);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     {
       grub_free (split_key);
@@ -323,12 +343,14 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
     }
 
   /* Try to recover master key from each active keyslot.  */
-  for (i = 0; i < ARRAY_SIZE (header->keyblock); i++)
+  for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
     {
       gcry_err_code_t gcry_err;
+      grub_uint8_t candidate_key[keysize];
+      grub_uint8_t digest[keysize];
 
       /* Check if keyslot is enabled.  */
-      if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED)
+      if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
        continue;
 
       grub_dprintf ("luks", "Trying keyslot %d\n", i);
@@ -336,9 +358,9 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
       /* Calculate the PBKDF2 of the user supplied passphrase.  */
       gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
                                     grub_strlen (passphrase),
-                                    header->keyblock[i].passwordSalt,
-                                    sizeof (header->keyblock[i].passwordSalt),
-                                    grub_be_to_cpu32 (header->keyblock[i].
+                                    header.keyblock[i].passwordSalt,
+                                    sizeof (header.keyblock[i].passwordSalt),
+                                    grub_be_to_cpu32 (header.keyblock[i].
                                                       passwordIterations),
                                     digest, keysize);
 
@@ -357,11 +379,11 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
          return grub_crypto_gcry_error (gcry_err);
        }
 
-      length = (keysize * grub_be_to_cpu32 (header->keyblock[i].stripes));
+      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
+                           grub_be_to_cpu32 (header.keyblock
                                              [i].keyMaterialOffset), 0,
                            length, split_key);
       if (err)
@@ -379,7 +401,7 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
 
       /* 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));
+                          grub_be_to_cpu32 (header.keyblock[i].stripes));
       if (gcry_err)
        {
          grub_free (split_key);
@@ -390,11 +412,11 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
 
       /* 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.keyBytes),
+                                    header.mkDigestSalt,
+                                    sizeof (header.mkDigestSalt),
                                     grub_be_to_cpu32
-                                    (header->mkDigestIterations),
+                                    (header.mkDigestIterations),
                                     candidate_digest,
                                     sizeof (candidate_digest));
       if (gcry_err)
@@ -405,8 +427,8 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
 
       /* 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)
+      if (grub_memcmp (candidate_digest, header.mkDigest,
+                      sizeof (header.mkDigest)) != 0)
        {
          grub_dprintf ("luks", "bad digest\n");
          continue;
@@ -430,204 +452,19 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header,
   return GRUB_ACCESS_DENIED;
 }
 
-static void
-luks_close (grub_cryptodisk_t luks)
-{
-  grub_crypto_cipher_close (luks->cipher);
-  grub_crypto_cipher_close (luks->secondary_cipher);
-  grub_crypto_cipher_close (luks->essiv_cipher);
-  grub_free (luks);
-}
-
-static grub_err_t
-grub_luks_scan_device_real (const char *name, grub_disk_t source)
-{
-  grub_err_t err;
-  struct grub_luks_phdr header;
-  grub_cryptodisk_t newdev, dev;
-
-  dev = grub_cryptodisk_get_by_source_disk (source);
-
-  if (dev)
-    return GRUB_ERR_NONE;
-
-  /* Read the LUKS header.  */
-  err = grub_disk_read (source, 0, 0, sizeof (header), &header);
-  if (err)
-    return err;
-
-  newdev = configure_ciphers (&header);
-  if (!newdev)
-    return grub_errno;
-
-  newdev->total_length = grub_disk_get_size (source) - newdev->offset;
-
-  err = luks_recover_key (newdev, &header, name, source);
-  if (err)
-    {
-      luks_close (newdev);
-      return err;
-    }
-
-  grub_cryptodisk_insert (newdev, name, source);
-
-  have_it = 1;
-
-  return GRUB_ERR_NONE;
-}
-
-#ifdef GRUB_UTIL
-grub_err_t
-grub_luks_cheat_mount (const char *sourcedev, const char *cheat)
-{
-  grub_err_t err;
-  struct grub_luks_phdr header;
-  grub_cryptodisk_t newdev, dev;
-  grub_disk_t source;
-
-  /* Try to open disk.  */
-  source = grub_disk_open (sourcedev);
-  if (!source)
-    return grub_errno;
-
-  dev = grub_cryptodisk_get_by_source_disk (source);
-
-  if (dev)
-    {
-      grub_disk_close (source);        
-      return GRUB_ERR_NONE;
-    }
-
-  /* Read the LUKS header.  */
-  err = grub_disk_read (source, 0, 0, sizeof (header), &header);
-  if (err)
-    return err;
-
-  newdev = configure_ciphers (&header);
-  if (!newdev)
-    {
-      grub_disk_close (source);
-      return grub_errno;
-    }
-
-  newdev->total_length = grub_disk_get_size (source) - newdev->offset;
-
-  err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat);
-  grub_disk_close (source);
-  if (err)
-    grub_free (newdev);
-
-  return err;
-}
-#endif
-
-static int
-grub_luks_scan_device (const char *name)
-{
-  grub_err_t err;
-  grub_disk_t source;
-
-  /* Try to open disk.  */
-  source = grub_disk_open (name);
-  if (!source)
-    return grub_errno;
-
-  err = grub_luks_scan_device_real (name, source);
-
-  grub_disk_close (source);
-  
-  if (err)
-    grub_print_error ();
-  return have_it && check_uuid ? 0 : 1;
-}
-
-#ifdef GRUB_UTIL
-
-void
-grub_util_luks_print_uuid (grub_disk_t disk)
-{
-  grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
-  grub_printf ("%s ", dev->uuid);
-}
-#endif
-
-static grub_err_t
-grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args)
-{
-  struct grub_arg_list *state = ctxt->state;
-
-  if (argc < 1 && !state[1].set)
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
-
-  have_it = 0;
-  if (state[0].set)
-    {
-      grub_cryptodisk_t dev;
-
-      dev = grub_cryptodisk_get_by_uuid (args[0]);
-      if (dev)
-       {
-         grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id);
-         return GRUB_ERR_NONE;
-       }
-
-      check_uuid = 1;
-      search_uuid = args[0];
-      grub_device_iterate (&grub_luks_scan_device);
-      search_uuid = NULL;
-
-      if (!have_it)
-       return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found");
-      return GRUB_ERR_NONE;
-    }
-  else if (state[1].set)
-    {
-      check_uuid = 0;
-      search_uuid = NULL;
-      grub_device_iterate (&grub_luks_scan_device);
-      search_uuid = NULL;
-      return GRUB_ERR_NONE;
-    }
-  else
-    {
-      grub_err_t err;
-      grub_disk_t disk;
-      grub_cryptodisk_t dev;
-
-      check_uuid = 0;
-      search_uuid = NULL;
-      disk = grub_disk_open (args[0]);
-      if (!disk)
-       return grub_errno;
-
-      dev = grub_cryptodisk_get_by_source_disk (disk);
-      if (dev)
-       {
-         grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id);
-         grub_disk_close (disk);
-         return GRUB_ERR_NONE;
-       }
-
-      err = grub_luks_scan_device_real (args[0], disk);
-
-      grub_disk_close (disk);
-
-      return err;
-    }
-}
-
-static grub_extcmd_t cmd;
+struct grub_cryptodisk_dev luks_crypto = {
+  .scan = configure_ciphers,
+  .recover_key = luks_recover_key
+};
 
 GRUB_MOD_INIT (luks)
 {
   COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid)
                       < GRUB_CRYPTODISK_MAX_UUID_LENGTH);
-  cmd = grub_register_extcmd ("luksmount", grub_cmd_luksmount, 0,
-                             N_("SOURCE|-u UUID|-a"),
-                             N_("Mount a LUKS device."), options);
+  grub_cryptodisk_dev_register (&luks_crypto);
 }
 
 GRUB_MOD_FINI (luks)
 {
-  grub_unregister_extcmd (cmd);
+  grub_cryptodisk_dev_unregister (&luks_crypto);
 }
index 642d77cf0307751e919d59ace1344452f68ff7ec..b6e8a673f1c564936a1851e90b93c43b90077ecd 100644 (file)
@@ -33,6 +33,7 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <grub/util/misc.h>
+#include <grub/cryptodisk.h>
 
 #ifdef HAVE_DEVICE_MAPPER
 # include <libdevmapper.h>
@@ -756,6 +757,94 @@ grub_util_get_dm_abstraction (const char *os_dev)
 #endif
 }
 
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <libgeom.h>
+
+/* FIXME: geom actually gives us the whole container hierarchy.
+   It can be used more efficiently than this.  */
+void
+grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
+{
+  struct gmesh mesh;
+  struct gclass *class;
+  int error;
+  struct ggeom *geom;
+
+  grub_util_info ("following geom '%s'", name);
+
+  error = geom_gettree (&mesh);
+  if (error != 0)
+    grub_util_error ("couldn't open geom");
+
+  LIST_FOREACH (class, &mesh.lg_class, lg_class)
+    if (strcasecmp (class->lg_name, "part") == 0)
+      break;
+  if (!class)
+    grub_util_error ("couldn't open geom part");
+
+  LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+    { 
+      struct gprovider *provider;
+      LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+       if (strcmp (provider->lg_name, name) == 0)
+         {
+           char *name_tmp = xstrdup (geom->lg_name);
+           grub_disk_addr_t off = 0;
+           struct gconfig *config;
+           grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
+
+           grub_util_follow_gpart_up (name_tmp, &off, name_out);
+           free (name_tmp);
+           LIST_FOREACH (config, &provider->lg_config, lg_config)
+             if (strcasecmp (config->lg_name, "start") == 0)
+               off += strtoull (config->lg_val, 0, 10);
+           if (off_out)
+             *off_out = off;
+           return;
+         }
+    }
+  grub_util_info ("geom '%s' has no parent", name);
+  if (name_out)
+    *name_out = xstrdup (name);
+  if (off_out)
+    *off_out = 0;
+}
+
+static const char *
+grub_util_get_geom_abstraction (const char *dev)
+{
+  char *whole;
+  struct gmesh mesh;
+  struct gclass *class;
+  const char *name;
+  int error;
+
+  if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+    return 0;
+  name = dev + sizeof ("/dev/") - 1;
+  grub_util_follow_gpart_up (name, NULL, &whole);
+
+  grub_util_info ("following geom '%s'", name);
+
+  error = geom_gettree (&mesh);
+  if (error != 0)
+    grub_util_error ("couldn't open geom");
+
+  LIST_FOREACH (class, &mesh.lg_class, lg_class)
+    {
+      struct ggeom *geom;
+      LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+       { 
+         struct gprovider *provider;
+         LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+           if (strcmp (provider->lg_name, name) == 0)
+             return class->lg_name;
+       }
+    }
+  return NULL;
+}
+#endif
+
 int
 grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
 {
@@ -777,6 +866,14 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
     return GRUB_DEV_ABSTRACTION_RAID;
 #endif
 
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+  const char *abs;
+  abs = grub_util_get_geom_abstraction (os_dev);
+  grub_util_info ("abstraction of %s is %s", os_dev, abs);
+  if (abs && grub_strcasecmp (abs, "eli") == 0)
+    return GRUB_DEV_ABSTRACTION_GELI;
+#endif
+
   /* No abstraction found.  */
   return GRUB_DEV_ABSTRACTION_NONE;
 }
@@ -869,6 +966,71 @@ grub_util_pull_device (const char *os_dev)
   ab = grub_util_get_dev_abstraction (os_dev);
   switch (ab)
     {
+    case GRUB_DEV_ABSTRACTION_GELI:
+      {
+       char *whole;
+       struct gmesh mesh;
+       struct gclass *class;
+       const char *name;
+       int error;
+       char *lastsubdev = NULL;
+
+       if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+         return;
+       name = os_dev + sizeof ("/dev/") - 1;
+       grub_util_follow_gpart_up (name, NULL, &whole);
+
+       grub_util_info ("following geom '%s'", name);
+
+       error = geom_gettree (&mesh);
+       if (error != 0)
+         grub_util_error ("couldn't open geom");
+
+       LIST_FOREACH (class, &mesh.lg_class, lg_class)
+         {
+           struct ggeom *geom;
+           LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+             { 
+               struct gprovider *provider;
+               LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+                 if (strcmp (provider->lg_name, name) == 0)
+                   {
+                     struct gconsumer *consumer;
+                     char *fname;
+                     char *uuid;
+
+                     LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer)
+                       break;
+                     if (!consumer)
+                       grub_util_error ("couldn't find geli consumer");
+                     fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name);
+                     grub_util_info ("consumer %s", consumer->lg_provider->lg_name);
+                     lastsubdev = consumer->lg_provider->lg_name;
+                     grub_util_pull_device (fname);
+                     free (fname);
+                   }
+             }
+         }
+       if (ab == GRUB_DEV_ABSTRACTION_GELI && lastsubdev)
+         {
+           char *fname = xasprintf ("/dev/%s", lastsubdev);
+           char *grdev = grub_util_get_grub_dev (fname);
+           free (fname);
+
+           if (grdev)
+             {
+               grub_err_t err;
+               err = grub_cryptodisk_cheat_mount (grdev, os_dev);
+               if (err)
+                 grub_util_error ("Can't mount crypto: %s", grub_errmsg);
+             }
+
+           grub_free (grdev);
+         }
+
+      }
+      break;
+
     case GRUB_DEV_ABSTRACTION_LVM:
     case GRUB_DEV_ABSTRACTION_LUKS:
 #ifdef HAVE_DEVICE_MAPPER
@@ -895,7 +1057,7 @@ grub_util_pull_device (const char *os_dev)
                grub_util_pull_device (subdev);
              }
          }
-       if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev)
+       if (ab == GRUB_DEV_ABSTRACTION_CRYPTO && lastsubdev)
          {
            char *grdev = grub_util_get_grub_dev (lastsubdev);
            dm_tree_free (tree);
@@ -904,7 +1066,7 @@ grub_util_pull_device (const char *os_dev)
                grub_err_t err;
                err = grub_luks_cheat_mount (grdev, os_dev);
                if (err)
-                 grub_util_error ("Can't mount LUKS: %s", grub_errmsg);
+                 grub_util_error ("Can't mount crypto: %s", grub_errmsg);
              }
            grub_free (grdev);
          }
@@ -959,6 +1121,8 @@ grub_util_get_grub_dev (const char *os_dev)
       {
        char *uuid, *dash;
        uuid = get_dm_uuid (os_dev);
+       if (!uuid)
+         break;
        dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-');
        if (dash)
          *dash = 0;
@@ -968,6 +1132,55 @@ grub_util_get_grub_dev (const char *os_dev)
       }
       break;
 
+    case GRUB_DEV_ABSTRACTION_GELI:
+      {
+       char *whole;
+       struct gmesh mesh;
+       struct gclass *class;
+       const char *name;
+       int error;
+
+       if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
+         return 0;
+       name = os_dev + sizeof ("/dev/") - 1;
+       grub_util_follow_gpart_up (name, NULL, &whole);
+
+       grub_util_info ("following geom '%s'", name);
+
+       error = geom_gettree (&mesh);
+       if (error != 0)
+         grub_util_error ("couldn't open geom");
+
+       LIST_FOREACH (class, &mesh.lg_class, lg_class)
+         {
+           struct ggeom *geom;
+           LIST_FOREACH (geom, &class->lg_geom, lg_geom)
+             { 
+               struct gprovider *provider;
+               LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
+                 if (strcmp (provider->lg_name, name) == 0)
+                   {
+                     struct gconsumer *consumer;
+                     char *fname;
+                     char *uuid;
+
+                     LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer)
+                       break;
+                     if (!consumer)
+                       grub_util_error ("couldn't find geli consumer");
+                     fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name);
+                     uuid = grub_util_get_geli_uuid (fname);
+                     if (!uuid)
+                       grub_util_error ("couldn't retrieve geli UUID");
+                     grub_dev = xasprintf ("cryptouuid/%s", uuid);
+                     free (fname);
+                     free (uuid);
+                   }
+             }
+         }
+      }
+      break;
+
     case GRUB_DEV_ABSTRACTION_RAID:
 
       if (os_dev[7] == '_' && os_dev[8] == 'd')
index 97e090222af53bab131331a68fd85298eb0950e8..6cace3746d8c6b02997147fc2090afcdd8575a18 100644 (file)
@@ -106,9 +106,7 @@ struct hd_geometry
 # include <libdevmapper.h>
 #endif
 
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <libgeom.h>
-#elif defined(__NetBSD__)
+#if defined(__NetBSD__)
 # define HAVE_DIOCGDINFO
 # include <sys/ioctl.h>
 # include <sys/disklabel.h>    /* struct disklabel */
@@ -226,6 +224,82 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name),
   return 0;
 }
 
+#if !defined(__MINGW32__)
+grub_uint64_t
+grub_util_get_fd_sectors (int fd, unsigned *log_secsize)
+{
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
+  defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+# if defined(__NetBSD__)
+  struct disklabel label;
+# else
+  unsigned long long nr;
+# endif
+  unsigned sector_size, log_sector_size;
+  struct stat st;
+
+  if (fstat (fd, &st) < 0)
+    grub_util_error ("fstat failed");
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+  if (! S_ISCHR (st.st_mode))
+# else
+  if (! S_ISBLK (st.st_mode))
+# endif
+    goto fail;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+    if (ioctl (fd, DIOCGMEDIASIZE, &nr))
+# elif defined(__APPLE__)
+    if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
+# elif defined(__NetBSD__)
+    configure_device_driver (fd);
+    if (ioctl (fd, DIOCGDINFO, &label) == -1)
+# else
+    if (ioctl (fd, BLKGETSIZE64, &nr))
+# endif
+      goto fail;
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+    if (ioctl (fd, DIOCGSECTORSIZE, &sector_size))
+# else
+    if (ioctl (fd, BLKSSZGET, &sector_size))
+# endif
+      goto fail;
+
+    if (sector_size & (sector_size - 1) || !sector_size)
+      goto fail;
+    for (log_sector_size = 0;
+        (1 << log_sector_size) < sector_size;
+        log_sector_size++);
+
+    if (log_secsize)
+      *log_secsize = log_sector_size;
+
+# if defined (__APPLE__)
+    return nr;
+# elif defined(__NetBSD__)
+    return label.d_secperunit;
+# else
+    if (nr & ((1 << log_sector_size) - 1))
+      grub_util_error ("unaligned device size");
+
+    return (nr >> log_sector_size);
+# endif
+
+ fail:
+  /* In GNU/Hurd, stat() will return the right size.  */
+#elif !defined (__GNU__)
+# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
+#endif
+
+  if (log_secsize)
+   *log_secsize = 9;
+
+  return st.st_size >> 9;
+}
+#endif
+
 static grub_err_t
 grub_util_biosdisk_open (const char *name, grub_disk_t disk,
                         grub_disk_pull_t pull __attribute__ ((unused)))
@@ -262,90 +336,30 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk,
 
     return GRUB_ERR_NONE;
   }
-#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \
-      defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
+#else
   {
-# if defined(__NetBSD__)
-    struct disklabel label;
-# else
-    unsigned long long nr;
-# endif
-    int sector_size;
     int fd;
 
     fd = open (map[drive].device, O_RDONLY);
     if (fd == -1)
       return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
 
+    disk->total_sectors = grub_util_get_fd_sectors (fd, &disk->log_sector_size);
+
 # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__)
     if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
 # else
     if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
 # endif
-      {
-       close (fd);
-       goto fail;
-      }
-    data->is_disk = 1;
-
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-    if (ioctl (fd, DIOCGMEDIASIZE, &nr))
-# elif defined(__APPLE__)
-    if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr))
-# elif defined(__NetBSD__)
-    configure_device_driver (fd);
-    if (ioctl (fd, DIOCGDINFO, &label) == -1)
-# else
-    if (ioctl (fd, BLKGETSIZE64, &nr))
-# endif
-      {
-       close (fd);
-       goto fail;
-      }
-
-    if (ioctl (fd, BLKSSZGET, &sector_size))
-       {
-         close (fd);
-        goto fail;
-       }
+      data->is_disk = 1;
 
     close (fd);
 
-    if (sector_size & (sector_size - 1) || !sector_size)
-      goto fail;
-    for (disk->log_sector_size = 0;
-        (1 << disk->log_sector_size) < sector_size;
-        disk->log_sector_size++);
-
-# if defined (__APPLE__)
-    disk->total_sectors = nr;
-# elif defined(__NetBSD__)
-    disk->total_sectors = label.d_secperunit;
-# else
-    disk->total_sectors = nr >> disk->log_sector_size;
-
-    if (nr & ((1 << disk->log_sector_size) - 1))
-      grub_util_error ("unaligned device size");
-# endif
-
     grub_util_info ("the size of %s is %llu", name, disk->total_sectors);
 
     return GRUB_ERR_NONE;
   }
-
- fail:
-  /* In GNU/Hurd, stat() will return the right size.  */
-#elif !defined (__GNU__)
-# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
 #endif
-  if (stat (map[drive].device, &st) < 0)
-    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device);
-
-  disk->total_sectors = st.st_size >> disk->log_sector_size;
-
-  grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
-
-  return GRUB_ERR_NONE;
 }
 
 int
@@ -367,55 +381,6 @@ grub_util_device_is_mapped (const char *dev)
 }
 
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
-/* FIXME: geom actually gives us the whole container hierarchy.
-   It can be used more efficiently than this.  */
-static void
-follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out)
-{
-  struct gmesh mesh;
-  struct gclass *class;
-  int error;
-  struct ggeom *geom;
-
-  grub_util_info ("following geom '%s'", name);
-
-  error = geom_gettree (&mesh);
-  if (error != 0)
-    grub_util_error ("couldn't open geom");
-
-  LIST_FOREACH (class, &mesh.lg_class, lg_class)
-    if (strcasecmp (class->lg_name, "part") == 0)
-      break;
-  if (!class)
-    grub_util_error ("couldn't open geom part");
-
-  LIST_FOREACH (geom, &class->lg_geom, lg_geom)
-    { 
-      struct gprovider *provider;
-      LIST_FOREACH (provider, &geom->lg_provider, lg_provider)
-       if (strcmp (provider->lg_name, name) == 0)
-         {
-           char *name_tmp = xstrdup (geom->lg_name);
-           grub_disk_addr_t off = 0;
-           struct gconfig *config;
-           grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name);
-
-           follow_geom_up (name_tmp, &off, name_out);
-           free (name_tmp);
-           LIST_FOREACH (config, &provider->lg_config, lg_config)
-             if (strcasecmp (config->lg_name, "start") == 0)
-               off += strtoull (config->lg_val, 0, 10);
-           if (off_out)
-             *off_out = off;
-           return;
-         }
-    }
-  grub_util_info ("geom '%s' has no parent", name);
-  if (name_out)
-    *name_out = xstrdup (name);
-  if (off_out)
-    *off_out = 0;
-}
 
 static grub_disk_addr_t
 find_partition_start (const char *dev)
@@ -423,10 +388,11 @@ find_partition_start (const char *dev)
   grub_disk_addr_t out;
   if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0)
     return 0;
-  follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL);
+  grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL);
 
   return out;
 }
+
 #elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
 static grub_disk_addr_t
 find_partition_start (const char *dev)
@@ -1508,7 +1474,7 @@ devmapper_out:
   char *out, *out2;
   if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
     return xstrdup (os_dev);
-  follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
+  grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out);
 
   out2 = xasprintf ("/dev/%s", out);
   free (out);
@@ -1667,6 +1633,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
   struct stat st;
   int drive;
 
+  grub_util_info ("Looking for %s", os_dev);
+
   if (stat (os_dev, &st) < 0)
     {
       grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
index 169fb119de6866c99a7767fc9ad216c8aae43a9d..c6d1ce8de8e04a6be99ddccc6eaba22d73b2bbe3 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <grub/disk.h>
 #include <grub/crypto.h>
+#include <grub/list.h>
 
 typedef enum
   {
@@ -57,6 +58,8 @@ typedef gcry_err_code_t
 
 struct grub_cryptodisk
 {
+  struct grub_cryptodisk *next;
+
   char *source;
   grub_disk_addr_t offset;
   grub_disk_addr_t total_length;
@@ -78,6 +81,7 @@ struct grub_cryptodisk
   grub_size_t iv_prefix_len;
 #ifdef GRUB_UTIL
   char *cheat;
+  const char *modname;
   int cheat_fd;
 #endif
   int log_sector_size;
@@ -86,10 +90,37 @@ struct grub_cryptodisk
   grub_uint8_t rekey_key[64];
   grub_uint64_t last_rekey;
   int rekey_derived_size;
-  struct grub_cryptodisk *next;
 };
 typedef struct grub_cryptodisk *grub_cryptodisk_t;
 
+struct grub_cryptodisk_dev
+{
+  struct grub_cryptodisk_dev *next;
+
+  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);
+};
+typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
+
+extern grub_cryptodisk_dev_t EXPORT_VAR (grub_cryptodisk_list);
+
+#ifndef GRUB_LST_GENERATOR
+static inline void
+grub_cryptodisk_dev_register (grub_cryptodisk_dev_t cr)
+{
+  grub_list_push (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr));
+}
+#endif
+
+static inline void
+grub_cryptodisk_dev_unregister (grub_cryptodisk_dev_t cr)
+{
+  grub_list_remove (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr));
+}
+
+#define FOR_CRYPTODISK_DEVS(var) FOR_LIST_ELEMENTS((var), (grub_cryptodisk_list))
+
 gcry_err_code_t
 grub_cryptodisk_setkey (grub_cryptodisk_t dev,
                        grub_uint8_t *key, grub_size_t keysize);
@@ -106,6 +137,8 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
                              grub_disk_t source, const char *cheat);
 void
 grub_util_cryptodisk_print_abstraction (grub_disk_t disk);
+char *
+grub_util_get_geli_uuid (const char *dev);
 #endif
 
 grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid);
index 57cd911efead980f1edd52de5e4e480339add63c..6921e567c75b016d53b80b8fd54cb97ffa76fcf8 100644 (file)
@@ -26,6 +26,7 @@ enum grub_dev_abstraction_types {
   GRUB_DEV_ABSTRACTION_LVM,
   GRUB_DEV_ABSTRACTION_RAID,
   GRUB_DEV_ABSTRACTION_LUKS,
+  GRUB_DEV_ABSTRACTION_GELI,
 };
 
 char *grub_find_device (const char *dir, dev_t dev);
@@ -38,5 +39,9 @@ const char *grub_util_check_char_device (const char *blk_dev);
 #ifdef __linux__
 char **grub_util_raid_getmembers (const char *name, int bootable);
 #endif
+#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
+void grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out,
+                               char **name_out);
+#endif
 
 #endif /* ! GRUB_UTIL_GETROOT_HEADER */
index 18191c4eb489e5ebab2063e6f14bfa4dbe3add0e..719faa29b5334009bf6d41ea60ae5810b8adcd71 100644 (file)
@@ -35,7 +35,11 @@ grub_err_t
 grub_util_fd_seek (int fd, const char *name, grub_uint64_t sector);
 ssize_t grub_util_fd_read (int fd, char *buf, size_t len);
 grub_err_t
-grub_luks_cheat_mount (const char *sourcedev, const char *cheat);
-void grub_util_luks_print_uuid (grub_disk_t disk);
+grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat);
+void grub_util_cryptodisk_print_uuid (grub_disk_t disk);
+#if !defined(__MINGW32__)
+grub_uint64_t
+grub_util_get_fd_sectors (int fd, unsigned *log_secsize);
+#endif
 
 #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
index 48a5be1ca5179ccef47892e38a6839d4491c70fe..f5880626c20fecffed5fd49bce1f43eadbccbe15 100644 (file)
@@ -309,10 +309,8 @@ fstest (int n, char **args)
     char *argv[2] = { "-a", NULL};
     if (mount_crypt)
       {
-       if (execute_command ("luksmount", 1, argv))
-         grub_util_error (_("luksmount command fails: %s"), grub_errmsg);
-       if (execute_command ("gelimount", 1, argv))
-         grub_util_error (_("gelimount command fails: %s"), grub_errmsg);
+       if (execute_command ("cryptomount", 1, argv))
+         grub_util_error (_("cryptomount command fails: %s"), grub_errmsg);
       }
   }
 
index 3b3383ab4041ba721852ba9d7166f50c56284fe4..049444e9347b3ae20ce610702723831cba0911f2 100644 (file)
@@ -538,9 +538,9 @@ if [ "x${devabstraction_module}" = "x" ] ; then
              
           exit 1
         fi
-       if [ x$GRUB_LUKS_ENABLE = xy ]; then
-           for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do
-               echo "luksmount -u $uuid"
+       if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+           for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do
+               echo "cryptomount -u $uuid"
            done
        fi
 
index 41e68bc1b251cbc2b81f5c92d86c695949ec708a..ade7a558dc293a3f6b109c23cfbe8a124d4b0e8c 100644 (file)
@@ -254,7 +254,7 @@ export GRUB_DEFAULT \
   GRUB_DISABLE_OS_PROBER \
   GRUB_INIT_TUNE \
   GRUB_SAVEDEFAULT \
-  GRUB_ENABLE_LUKS \
+  GRUB_ENABLE_CRYPTODISK \
   GRUB_BADRAM
 
 if test "x${grub_cfg}" != "x"; then
index 1664b6bbe156a6463ffba79877479e9a3c32f91d..33ee7e4328cbefb2b1647ebf1c2b5d03cfe63604 100644 (file)
@@ -69,12 +69,12 @@ is_path_readable_by_grub ()
     return 1
   fi
 
-  if [ x$GRUB_LUKS_ENABLE = xy ]; then
+  if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
       return 0
   fi
   
   for abstraction in $abstractions; do
-      if [ "x$abstraction" = xluks ]; then
+      if [ "x$abstraction" = xcryptodisk ]; then
          return 1
       fi
   done
@@ -138,9 +138,9 @@ prepare_grub_to_access_device ()
     echo "insmod ${module}"
   done
 
-  if [ x$GRUB_LUKS_ENABLE = xy ]; then
-      for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do
-         echo "luksmount -u $uuid"
+  if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then
+      for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do
+         echo "cryptomount -u $uuid"
       done
   fi
 
index f5d93ac4e5607fd50b3d0762337a8ed4b9db94e1..7c0a75123dc6ee0ca1870cd2b965eda31c9ee8f5 100644 (file)
@@ -56,7 +56,7 @@ enum {
   PRINT_DEVICE,
   PRINT_PARTMAP,
   PRINT_ABSTRACTION,
-  PRINT_LUKS_UUID
+  PRINT_CRYPTODISK_UUID
 };
 
 int print = PRINT_FS;
@@ -91,7 +91,7 @@ probe_partmap (grub_disk_t disk)
 }
 
 static void
-probe_luks_uuid (grub_disk_t disk)
+probe_cryptodisk_uuid (grub_disk_t disk)
 {
   grub_disk_memberlist_t list = NULL, tmp;
 
@@ -102,14 +102,13 @@ probe_luks_uuid (grub_disk_t disk)
     }
   while (list)
     {
-      probe_luks_uuid (list->disk);
+      probe_cryptodisk_uuid (list->disk);
       tmp = list->next;
       free (list);
       list = tmp;
     }
-  /* FIXME: support non-LUKS.  */
   if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
-    grub_util_luks_print_uuid (disk);
+    grub_util_cryptodisk_print_uuid (disk);
 }
 
 static int
@@ -215,9 +214,9 @@ probe (const char *path, char *device_name)
       goto end;
     }
 
-  if (print == PRINT_LUKS_UUID)
+  if (print == PRINT_CRYPTODISK_UUID)
     {
-      probe_luks_uuid (dev->disk);
+      probe_cryptodisk_uuid (dev->disk);
       printf ("\n");
       goto end;
     }
@@ -295,8 +294,8 @@ Probe device information for a given path (or device, if the -d option is given)
 \n\
   -d, --device              given argument is a system device, not a path\n\
   -m, --device-map=FILE     use FILE as the device map [default=%s]\n\
-  -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|luks_uuid)\n\
-                            print filesystem module, GRUB drive, system device, partition map module, abstraction module or LUKS UUID [default=fs]\n\
+  -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid)\n\
+                            print filesystem module, GRUB drive, system device, partition map module, abstraction module or CRYPTO UUID [default=fs]\n\
   -h, --help                display this message and exit\n\
   -V, --version             print version information and exit\n\
   -v, --verbose             print verbose messages\n\
@@ -354,8 +353,8 @@ main (int argc, char *argv[])
              print = PRINT_PARTMAP;
            else if (!strcmp (optarg, "abstraction"))
              print = PRINT_ABSTRACTION;
-           else if (!strcmp (optarg, "luks_uuid"))
-             print = PRINT_LUKS_UUID;
+           else if (!strcmp (optarg, "cryptodisk_uuid"))
+             print = PRINT_CRYPTODISK_UUID;
            else
              usage (1);
            break;