grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 0/1] plainmount: Support plain encryption mode.


From: Maxim Fomin
Subject: [PATCH v2 0/1] plainmount: Support plain encryption mode.
Date: Sat, 02 Apr 2022 20:02:17 +0000

---
 docs/grub.texi              |  47 ++++
 grub-core/Makefile.core.def |   5 +
 grub-core/disk/plainmount.c | 511 ++++++++++++++++++++++++++++++++++++
 3 files changed, 563 insertions(+)
 create mode 100644 grub-core/disk/plainmount.c

diff --git a/docs/grub.texi b/docs/grub.texi
index caba8befb..1e4126569 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4071,6 +4071,7 @@ you forget a command, you can run the command 
@command{help}
 * parttool::                    Modify partition table entries
 * password::                    Set a clear-text password
 * password_pbkdf2::             Set a hashed password
+* plainmount::                  Open device encrypted in plain mode.
 * play::                        Play a tune
 * probe::                       Retrieve device info
 * rdmsr::                       Read values from model-specific registers
@@ -4363,6 +4364,9 @@ function is supported, as Argon2 is not yet supported.

 Also, note that, unlike filesystem UUIDs, UUIDs for encrypted devices must be
 specified without dash separators.
+
+Support for plain encryption mode (plain dm-crypt) is provided via separate
+plainmount command.
 @end deffn

 @node cutmem
@@ -4929,6 +4933,49 @@ to generate password hashes.  @xref{Security}.
 @end deffn


+@node plainmount
+@subsection plainmount
+
+@deffn Command plainmount device [@option{-h} hash] [@option{-c} cipher] 
[@option{-o} offset] [@option{-b} disk size] [@option{-s} key size] 
[@option{-S} sector size] [@option{-p} password] [@option{-d} keyfile] 
[@option{-O} keyfile offset]
+
+Setup access to encrypted in plain mode device. Password can be specified in
+two ways: as a secret passphrase or as a byte array from keyfile or device
+block with the option @option{-d}. Passphrase can be provided interactively
+from console or with option @option{-p}. Keyfile/device block can be a regular
+file or some partition/disk. The length of the key from keyfile/device block
+is limited by @option{-O} (offset of device first block) and @option{-s} (key
+size) options and cannot be larger than cryptomount limit (currently 128 
bytes).
+
+Cipher @option{-c} and keysize @option{-s} options are mandatory. Hash option
+@option{-h} is mandatory if keyfile/disk block is not specified. The keyfile
+parameter @option{-d} has higher priority than option @option{-p}.
+
+Option @option{-S} determines encrypted disk block size and can be 512 
(default)
+or 1024, 2048, 4096 bytes. Note: disk sector size in plain mode is set at 
encryption
+time, attempt to decrypt already created device with diffferent sector size 
will
+result in error.
+
+Options @option{-o}, @option{-b} and @option{-O} are interpreted as size in
+term of bytes where suffixes 'K', 'M' and 'G' (1024^N) are available.
+
+Options @option{-s} must be specified in bits (for example: -s 256 or -s 512).
+
+The plainmount command can report internal cryptographic errors. If it happens,
+check hash, key size and cipher options - they should match each other.
+Successfully decrypted disks are named as (cryptoX) and have linear numeration
+with other decrypted devices opened by cryptodisk.
+
+Note, all encryption arguments (cipher, hash, key size, disk offset and disk
+sector size) must match those which were used to setup encrypted device. If
+any of them does not match actual argument used during initial encryption,
+plainmount will return garbage data and GRUB will report unknown filesystem
+of opened disk. Note, writing data to such virtual device will result in data
+loss if underlying partition hosted some filesystem. If encrypted disk hosts
+some high level abstraction (like LVM2 or MDRAID) it will be created under
+separate name.
+@end deffn
+
+
 @node play
 @subsection play

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8022e1c0a..ce8478055 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1184,6 +1184,11 @@ module = {
   common = disk/luks.c;
 };

+module = {
+  name = plainmount;
+  common = disk/plainmount.c;
+};
+
 module = {
   name = luks2;
   common = disk/luks2.c;
diff --git a/grub-core/disk/plainmount.c b/grub-core/disk/plainmount.c
new file mode 100644
index 000000000..1e467bcc8
--- /dev/null
+++ b/grub-core/disk/plainmount.c
@@ -0,0 +1,511 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007,2010,2011,2019  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/cryptodisk.h>
+#include <grub/dl.h>
+#include <grub/err.h>
+#include <grub/extcmd.h>
+#include <grub/partition.h>
+#include <grub/file.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options[] =
+  {
+    /* TRANSLATORS: It's still restricted to this module only.  */
+    {"hash", 'h', 0, N_("Password hash"), 0, ARG_TYPE_STRING},
+    {"cipher", 'c', 0, N_("Password cipher"), 0, ARG_TYPE_STRING},
+    {"offset", 'o', 0, N_("Device offset"), 0, ARG_TYPE_STRING},
+    {"disk-size", 'b', 0, N_("Device size"), 0, ARG_TYPE_STRING},
+    {"key-size", 's', 0, N_("Key size (in bits)"), 0, ARG_TYPE_INT},
+    {"sector-size", 'S', 0, N_("Device sector size"), 0, ARG_TYPE_INT},
+    {"password", 'p', 0, N_("Password (key)"), 0, ARG_TYPE_STRING},
+    {"keyfile", 'd', 0, N_("Keyfile/disk path"), 0, ARG_TYPE_STRING},
+    {"keyfile-offset", 'O', 0, N_("Keyfile offset."), 0, ARG_TYPE_STRING},
+    {0, 0, 0, 0, 0, 0}
+  };
+
+struct grub_plainmount_args
+{
+  char *key_data, *cipher, *mode, *hash, *keyfile;
+  grub_size_t offset, size, key_size, sector_size, keyfile_offset;
+  grub_disk_t disk;
+};
+typedef struct grub_plainmount_args *grub_plainmount_args_t;
+
+
+/* Cryptodisk setkey() function wrapper */
+static grub_err_t
+plainmount_setkey (grub_cryptodisk_t dev, grub_uint8_t *data,
+                   grub_size_t size)
+{
+  gcry_err_code_t code = grub_cryptodisk_setkey (dev, data, size);
+  if (code != GPG_ERR_NO_ERROR)
+    {
+      grub_dprintf ("plainmount", "password crypto status is %d\n", code);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                         N_("cannot set key from password. "
+                            "Check keysize/hash/cipher options."));
+    }
+  return GRUB_ERR_NONE;
+}
+
+
+/* Parse disk size suffix */
+static grub_size_t plainmount_parse_suffix (char *arg)
+{
+  const char *p = NULL;
+  grub_errno = GRUB_ERR_NONE;
+  grub_size_t val = grub_strtoull (arg, &p, 0);
+  switch (*p)
+    {
+      case 'K':
+      case 'k':
+        val = val * 1024;
+        break;
+      case 'M':
+      case 'm':
+        val = val * 1024*1024;
+        break;
+      case 'G':
+      case 'g':
+        val = val * 1024*1024*1024;
+        break;
+      case '\0':
+        break;
+      default:
+        val = (grub_size_t) -1;
+    }
+  return val;
+}
+
+/* Configure cryptodisk uuid */
+static void plainmount_set_uuid (grub_cryptodisk_t dev)
+{
+  grub_size_t pos = 0;
+  static const char *uuid = "00000000-0000-0000-0000-000000000000";
+  grub_snprintf (dev->uuid, sizeof (dev->uuid)-1, "%32lu", dev->id+1);
+  while (dev->uuid[pos++] == ' ');
+  grub_memcpy (dev->uuid, uuid, pos-1);
+  COMPILE_TIME_ASSERT (sizeof (dev->uuid) >= sizeof (uuid));
+}
+
+
+/* Configure cryptodevice sector size (-S option) */
+static grub_err_t
+plainmount_configure_sectors (grub_cryptodisk_t dev, grub_plainmount_args_t 
cargs)
+{
+  grub_disk_addr_t total_sectors;
+
+  /* cryptsetup allows only 512/1024/2048/4096 byte sectors */
+  if (!(cargs->sector_size == 512 || cargs->sector_size == 1024 ||
+        cargs->sector_size == 2048 || cargs->sector_size == 4096))
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("invalid sector size -S %"PRIuGRUB_SIZE
+                              ", only 512/1024/2048/4096 are allowed"),
+                           cargs->sector_size);
+  switch (cargs->sector_size)
+    {
+      case 1024:
+        dev->log_sector_size = 10;
+        break;
+      case 2048:
+        dev->log_sector_size = 11;
+        break;
+      case 4096:
+        dev->log_sector_size = 12;
+        break;
+      default:
+        dev->log_sector_size = 9;
+    }
+
+  /* Convert size to sectors */
+  if (cargs->size)
+    total_sectors = cargs->size / 512;
+  else
+    {
+      total_sectors = grub_disk_native_sectors (cargs->disk);
+      if (total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+        return grub_error (GRUB_ERR_BAD_DEVICE,
+                           N_("cannot determine disk %s size"),
+                           cargs->disk->name);
+    }
+  total_sectors = grub_convert_sector (total_sectors, GRUB_DISK_SECTOR_BITS,
+                                       dev->log_sector_size);
+  if (total_sectors == 0)
+    return grub_error (GRUB_ERR_BAD_DEVICE,
+                       N_("cannot determine disk size"));
+  dev->offset_sectors = grub_divmod64 (cargs->offset, cargs->sector_size, 
NULL);
+  if (total_sectors <= dev->offset_sectors)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       N_("specified disk offset is larger than disk size"));
+  dev->total_sectors = total_sectors - dev->offset_sectors;
+  grub_dprintf ("plainmount", "log_sector_size=%d, 
total_sectors=%"PRIuGRUB_SIZE
+                ", offset_sectors=%"PRIuGRUB_SIZE"\n", dev->log_sector_size,
+                dev->total_sectors, dev->offset_sectors);
+  return GRUB_ERR_NONE;
+}
+
+
+/* Hashes a password into a key and stores it with cipher. */
+static grub_err_t
+plainmount_configure_password (grub_cryptodisk_t dev, grub_plainmount_args_t 
cargs)
+{
+  const gcry_md_spec_t *hash = NULL;
+  grub_uint8_t derived_hash[GRUB_CRYPTODISK_MAX_KEYLEN * 2], *dh = 
derived_hash;
+  char *p;
+  unsigned int round, i;
+  unsigned int len, size;
+
+  /* Check hash */
+  hash = grub_crypto_lookup_md_by_name (cargs->hash);
+  if (!hash)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+                       N_("couldn't load %s hash (perhaps a typo?)"),
+                       cargs->hash);
+
+  if (hash->mdlen > GRUB_CRYPTODISK_MAX_KEYLEN)
+        return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("hash length %"PRIuGRUB_SIZE
+                              " exceeds maximum %d bits"),
+                           hash->mdlen, GRUB_CRYPTODISK_MAX_KEYLEN * 8);
+  dev->hash = hash;
+
+  /* Hack to support the "none" hash */
+  if (dev->hash)
+    len = dev->hash->mdlen;
+  else
+    len = cargs->key_size;
+
+  /* Option -p was not set */
+  if (cargs->key_data[0] == '\0')
+  {
+    grub_disk_t source = cargs->disk;
+    char *part = grub_partition_get_name (source->partition);
+    grub_printf_ (N_("Enter passphrase for %s%s%s: "), source->name,
+                  source->partition != NULL ? "," : "",
+                  part != NULL ? part : N_("UNKNOWN"));
+    grub_free (part);
+
+    if (!grub_password_get (cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE-1))
+        grub_error (GRUB_ERR_BAD_ARGUMENT, N_("password not supplied"));
+  }
+
+  p = grub_malloc (cargs->key_size + 2 + cargs->key_size / len);
+  if (!p)
+    return GRUB_ERR_OUT_OF_MEMORY;
+
+  /* Hash password */
+  for (round = 0, size = cargs->key_size; size; round++, dh += len, size -= 
len)
+    {
+      for (i = 0; i < round; i++)
+       p[i] = 'A';
+
+      grub_strcpy (p + i, cargs->key_data);
+
+      if (len > size)
+       len = size;
+
+      grub_crypto_hash (dev->hash, dh, p, grub_strlen (p));
+    }
+  grub_free (p);
+  return plainmount_setkey (dev, derived_hash, cargs->key_size);
+}
+
+
+/* Read keyfile as a file */
+static grub_err_t
+plainmount_configure_keyfile (grub_cryptodisk_t dev, grub_plainmount_args_t 
cargs)
+{
+  grub_file_t keyfile = grub_file_open (cargs->keyfile, GRUB_FILE_TYPE_NONE);
+  if (!keyfile)
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("cannot open keyfile %s"),
+                       cargs->keyfile);
+
+  if (grub_file_seek (keyfile, cargs->keyfile_offset) == (grub_off_t)-1)
+      return grub_error (GRUB_ERR_FILE_READ_ERROR,
+                        N_("cannot seek keyfile at offset %"PRIuGRUB_SIZE),
+                        cargs->keyfile_offset);
+
+  if (cargs->key_size > (keyfile->size - cargs->keyfile_offset))
+      return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                         N_("Specified key size (%"PRIuGRUB_SIZE") is too 
small"
+                            " for keyfile size (%"PRIuGRUB_SIZE") and offset 
(%"
+                            PRIuGRUB_SIZE")"),
+                         cargs->key_size, keyfile->size,
+                         cargs->keyfile_offset);
+  else
+    cargs->key_size = keyfile->size - cargs->keyfile_offset;
+
+  if (grub_file_read (keyfile, cargs->key_data, cargs->key_size) !=
+       (grub_ssize_t) cargs->key_size)
+     return grub_error (GRUB_ERR_FILE_READ_ERROR, N_("error reading key 
file"));
+
+  return plainmount_setkey (dev, (grub_uint8_t*)cargs->key_data, 
cargs->key_size);
+}
+
+
+/* Read keyfile as a disk segment */
+static grub_err_t
+plainmount_configure_keydisk (grub_cryptodisk_t dev, grub_plainmount_args_t 
cargs)
+{
+  grub_err_t err;
+
+  char *keydisk_name = grub_file_get_device_name (cargs->keyfile);
+  grub_disk_t keydisk = grub_disk_open (cargs->keyfile);
+  if (!keydisk)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unable to open disk %s"),
+                         keydisk_name);
+      goto cleanup;
+    }
+  if (grub_disk_read (keydisk, 0, cargs->keyfile_offset,
+                      cargs->key_size, cargs->key_data) != GRUB_ERR_NONE)
+    {
+      err = grub_error (GRUB_ERR_READ_ERROR, N_("failed to read from disk %s"),
+                        keydisk_name);
+      goto cleanup;
+    }
+  err = plainmount_setkey (dev, (grub_uint8_t*)cargs->key_data, 
cargs->key_size);
+
+cleanup:
+  grub_free (keydisk_name);
+  if (keydisk)
+    grub_disk_close (keydisk);
+  return err;
+}
+
+
+/* Plainmount command entry point */
+static grub_err_t
+grub_cmd_plainmount (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+  struct grub_arg_list *state = ctxt->state;
+  struct grub_plainmount_args cargs = {0};
+  grub_cryptodisk_t dev = NULL;
+  char *diskname = NULL, *disklast = NULL;
+  grub_size_t len;
+  grub_err_t err = GRUB_ERR_BUG;
+  const char *p = NULL;
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("device name required"));
+
+  /* Open SOURCE disk */
+  diskname = args[0];
+  len = grub_strlen (diskname);
+  if (len && diskname[0] == '(' && diskname[len - 1] == ')')
+    {
+      disklast = &diskname[len - 1];
+      *disklast = '\0';
+      diskname++;
+    }
+  cargs.disk = grub_disk_open (diskname);
+  if (!cargs.disk)
+    {
+      if (disklast)
+        *disklast = ')';
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                        N_("cannot open disk %s"), diskname);
+      goto exit;
+    }
+
+  /* Check whether required arguments are specified */
+  if (!state[1].set || !state[4].set)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, "cipher/key size must be set");
+      goto exit;
+    }
+  if (!state[0].set && !state[7].set)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, "hash algorithm must be set");
+      goto exit;
+    }
+
+  /* Allocate all stuff here */
+  cargs.hash =  state[0].set ? grub_strdup (state[0].arg) : NULL;
+  cargs.cipher = grub_strdup (state[1].arg);
+  cargs.keyfile = state[7].set ? grub_strdup (state[7].arg) : NULL;
+  dev = grub_zalloc (sizeof *dev);
+  cargs.key_data = grub_zalloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+  if ((!cargs.hash && state[0].set) || !cargs.cipher ||
+      (!cargs.keyfile && state[7].set) || !dev || !cargs.key_data)
+    {
+      err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+      goto exit;
+    }
+
+  /* Parse cmdline arguments */
+  if (state[2].set)
+    {
+      cargs.offset = plainmount_parse_suffix (state[2].arg);
+      if (cargs.offset == (grub_size_t)-1)
+        {
+          err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                           N_("unrecognized offset suffix"));
+          goto exit;
+        }
+    }
+  if (state[3].set)
+  {
+    cargs.size = grub_strtoull (state[3].arg, &p, 0);
+    cargs.size = plainmount_parse_suffix (state[3].arg);
+    if (cargs.size == (grub_size_t)-1)
+      {
+        err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                         N_("unrecognized disk size suffix"));
+        goto exit;
+      }
+  }
+  grub_errno = GRUB_ERR_NONE;
+  cargs.key_size = grub_strtoull (state[4].arg, &p, 0) / 8;
+  if (state[4].set && (*p != '\0' || grub_errno != GRUB_ERR_NONE))
+   {
+     err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized key size"));
+     goto exit;
+   }
+  cargs.sector_size = state[5].set ? grub_strtoull (state[5].arg, &p, 0) : 512;
+  if (state[5].set && (*p != '\0' || grub_errno != GRUB_ERR_NONE))
+   {
+     err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized sector size"));
+     goto exit;
+   }
+  if (state[8].set)
+  {
+    cargs.keyfile_offset = plainmount_parse_suffix (state[8].arg);
+    if (cargs.keyfile_offset == (grub_size_t)-1)
+      {
+        err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                         N_("unrecognized keyfile offset suffix"));
+        goto exit;
+      }
+  }
+
+  /* Check key size */
+  if (cargs.key_size > GRUB_CRYPTODISK_MAX_KEYLEN)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                        N_("invalid key size %"PRIuGRUB_SIZE
+                           " (exceeds maximum %d bits)"),
+                        cargs.key_size, GRUB_CRYPTODISK_MAX_KEYLEN * 8);
+      goto exit;
+    }
+
+   /* Check password size */
+   if (state[6].set && grub_strlen (state[6].arg) + 1 >
+       GRUB_CRYPTODISK_MAX_PASSPHRASE)
+     {
+       err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                        N_("password exceeds maximium size"));
+       goto exit;
+     }
+   if (state[6].set)
+    grub_strcpy (cargs.key_data, state[6].arg);
+
+  /* Check cipher mode */
+  cargs.mode = grub_strchr (cargs.cipher,'-');
+  if (!cargs.mode)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid cipher mode"));
+      goto exit;
+    }
+  else
+    *cargs.mode++ = '\0';
+
+  /* Check cipher */
+  if (grub_cryptodisk_setcipher (dev, cargs.cipher, cargs.mode)!= 
GRUB_ERR_NONE)
+    {
+      err = grub_error (GRUB_ERR_BAD_ARGUMENT,
+                       N_("invalid cipher %s"), cargs.cipher);
+      goto exit;
+    }
+
+  /* Warn if hash and keyfile are both provided */
+  if (cargs.keyfile && state[0].arg)
+    grub_printf_ (N_("warning: hash is ignored if keyfile is specified\n"));
+
+  /* Warn if key file offset is provided without key file */
+  if (!state[7].set && state[8].set)
+    grub_printf_ (N_("warning: keyfile offset without keyfile is ignored\n"));
+
+  /* Warn if -p option is specified with keyfile */
+  if (state[6].set && state[7].set)
+    grub_printf_ (N_("warning: password specified with -p option"
+                     "is ignored if keyfile is provided\n"));
+
+  grub_dprintf ("plainmount",
+              "parameters: cipher=%s, hash=%s, key_size=%"PRIuGRUB_SIZE
+             ", keyfile=%s, keyfile offset=%"PRIuGRUB_SIZE"\n",
+              cargs.cipher, cargs.hash, cargs.key_size,
+              cargs.keyfile ? cargs.keyfile : NULL,
+              cargs.keyfile_offset);
+
+  err = plainmount_configure_sectors (dev, &cargs);
+  if (err != GRUB_ERR_NONE)
+    goto exit;
+
+  /* Configure keyfile/keydisk/password */
+  if (cargs.keyfile)
+    if (grub_strchr (cargs.keyfile, '/'))
+      err = plainmount_configure_keyfile (dev, &cargs);
+    else
+      err = plainmount_configure_keydisk (dev, &cargs);
+  else
+    err = plainmount_configure_password (dev, &cargs);
+  if (err != GRUB_ERR_NONE)
+    goto exit;
+
+  err = grub_cryptodisk_insert (dev, diskname, cargs.disk);
+  if (err != GRUB_ERR_NONE)
+    {
+      grub_printf_ (N_("cannot initialize cryptodisk. "
+                    "Check cipher/key size/hash arguments.\n"));
+      goto exit;
+    }
+
+  dev->modname = "plainmount";
+  dev->source_disk = cargs.disk;
+  plainmount_set_uuid (dev);
+
+exit:
+  grub_free (cargs.hash);
+  grub_free (cargs.cipher);
+  grub_free (cargs.keyfile);
+  grub_free (cargs.key_data);
+  if (err != GRUB_ERR_NONE && cargs.disk)
+    grub_disk_close (cargs.disk);
+  if (err != GRUB_ERR_NONE && dev)
+    grub_free (dev);
+  return err;
+}
+
+static grub_extcmd_t cmd;
+GRUB_MOD_INIT (plainmount)
+{
+  cmd = grub_register_extcmd ("plainmount", grub_cmd_plainmount, 0,
+                             N_("[-h hash] [-c cipher] [-o offset] [-b 
disk-size]"
+                             " [-s key-size] [-S sector-size] [-p password] "
+                             "[[-d keyfile] [-O keyfile offset]] <SOURCE>"),
+                             N_("Open partition encrypted in plain mode."),
+                             options);
+}
+
+GRUB_MOD_FINI (plainmount)
+{
+  grub_unregister_extcmd (cmd);
+}
--
2.35.1



reply via email to

[Prev in Thread] Current Thread [Next in Thread]