All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
To: Patrick Steinhardt <ps@pks.im>,
	Daniel Kiper <daniel.kiper@oracle.com>,
	Glenn Washburn <development@efficientek.com>
Cc: The development of GNU GRUB <grub-devel@gnu.org>,
	John Lane <john@lane.uk.net>,
	Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
Subject: [PATCH v7 5/6] cryptodisk: enable the backends to implement key files
Date: Thu, 10 Dec 2020 10:14:58 +0100	[thread overview]
Message-ID: <20201210091459.11154-6-GNUtoo@cyberdimension.org> (raw)
In-Reply-To: <20201210091459.11154-1-GNUtoo@cyberdimension.org>

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

Signed-off-by: John Lane <john@lane.uk.net>
GNUtoo@cyberdimension.org: rebase, patch split, small fixes, commit message
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
Changelog since v3:
-------------------
- Fixed the size formating with PRIuGRUB_SIZE
- Added Reviewed-by

ChangeLog since v4:
-------------------
- Style fixes:
  - Added missing space between function and '('
  - Removed trailing backslashes in split strings

ChangeLog since v5:
-------------------
- No changes

ChangeLog since v6:
-------------------
- Fixed format string conversions issues found by Glenn Washburn:
  - "The type of keyfile->size is grub_off_t which is 
     typedef'd from grub_uint64_t. 
     [...] when compiling for i386, PRIuGRUB_SIZE expands
     to %lu, which accepts a 32-bit uint.
     This will cause the strict format string checking to fail 
     the build."
  - "The macro GRUB_CRYPTODISK_MAX_KEYFILE_SIZE gets expanded
     to an integer literal which gets type cast as an int,
     but PRIuGRUB_SIZE expects long or long long."
- Rebased. The rebase was needed due this commits:
  - 0eb44d319 luks2: Rename source disk variable named
                     "disk" to "source" as in luks.c
    => No changes to this patch, it just shows in the
       context lines.


---
 grub-core/disk/cryptodisk.c | 86 ++++++++++++++++++++++++++++++++++++-
 grub-core/disk/geli.c       |  7 +--
 grub-core/disk/luks.c       |  7 ++-
 grub-core/disk/luks2.c      |  7 +--
 include/grub/cryptodisk.h   |  5 ++-
 include/grub/file.h         |  2 +
 6 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index fec949ad0..11c0f7ab6 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -42,6 +42,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 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}
   };
 
@@ -969,6 +972,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_ssize_t key_size;
 
 static void
 cryptodisk_close (grub_cryptodisk_t dev)
@@ -999,7 +1004,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, key_size);
     if (err)
     {
       cryptodisk_close (dev);
@@ -1109,6 +1114,85 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
     hdr = NULL;
 
   have_it = 0;
+  key = NULL;
+
+  if (state[4].set) /* keyfile */
+    {
+      const char *p = NULL;
+      grub_file_t keyfile;
+      int keyfile_offset;
+      grub_size_t requested_keyfile_size = 0;
+
+
+      if (state[5].set) /* keyfile-offset */
+	{
+	  keyfile_offset = grub_strtoul (state[5].arg, &p, 0);
+
+	  if (grub_errno != GRUB_ERR_NONE)
+	    return grub_errno;
+
+	  if (*p != '\0')
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			       N_("unrecognized number"));
+	}
+      else
+	{
+	  keyfile_offset = 0;
+	}
+
+      if (state[6].set) /* keyfile-size */
+	{
+	  requested_keyfile_size = grub_strtoul (state[6].arg, &p, 0);
+
+	  if (*p != '\0')
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			       N_("unrecognized number"));
+
+	  if (grub_errno != GRUB_ERR_NONE)
+	    return grub_errno;
+
+	  if (requested_keyfile_size > GRUB_CRYPTODISK_MAX_KEYFILE_SIZE)
+	    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			      N_("Key file size exceeds maximum (%d)\n"),
+			      GRUB_CRYPTODISK_MAX_KEYFILE_SIZE);
+
+	  if (requested_keyfile_size == 0)
+	    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			      N_("Key file size is 0\n"));
+	}
+
+      keyfile = grub_file_open (state[4].arg,
+				GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY);
+      if (!keyfile)
+	return grub_errno;
+
+      if (grub_file_seek (keyfile, keyfile_offset) == (grub_off_t)-1)
+	return grub_errno;
+
+      if (requested_keyfile_size)
+	{
+	  if (requested_keyfile_size > (keyfile->size - keyfile_offset))
+	    return grub_error (GRUB_ERR_FILE_READ_ERROR,
+			       N_("Keyfile is too small: "
+				  "requested %" PRIuGRUB_SIZE " bytes, "
+				  "but the file only has %" PRIuGRUB_UINT64_T
+				  " bytes.\n"),
+			       requested_keyfile_size,
+			       keyfile->size);
+
+	  key_size = requested_keyfile_size;
+	}
+      else
+	{
+	  key_size = keyfile->size - keyfile_offset;
+	}
+
+      if (grub_file_read (keyfile, keyfile_buffer, key_size) != key_size)
+	return grub_error (GRUB_ERR_FILE_READ_ERROR,
+			   (N_("Error reading key file\n")));
+      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 d4d537e05..8fb24cc5b 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -404,7 +404,8 @@ geli_scan (grub_disk_t disk, const char *check_uuid, int boot_only,
 }
 
 static grub_err_t
-geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
+geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr,
+		  grub_uint8_t *key, grub_size_t keyfile_size)
 {
   grub_size_t keysize;
   grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@@ -420,8 +421,8 @@ geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
   grub_disk_addr_t sector;
   grub_err_t err;
 
-  /* Detached headers are not implemented yet */
-  if (hdr)
+  /* Detached headers and keyfiles are not implemented yet */
+  if (hdr || key || keyfile_size)
     return GRUB_ERR_NOT_IMPLEMENTED_YET;
 
   if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 1c518902b..b7867585a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -162,7 +162,8 @@ luks_scan (grub_disk_t disk, const char *check_uuid, int check_boot,
 }
 
 static grub_err_t
-luks_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
+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)
 {
   struct grub_luks_phdr header;
   grub_size_t keysize;
@@ -176,6 +177,10 @@ luks_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
   char *tmp;
   grub_uint32_t sector;
 
+  /* Keyfiles are not implemented yet */
+  if (keyfile_bytes || keyfile_bytes_size)
+     return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
   if (hdr)
     {
       if (grub_file_seek (hdr, 0) == (grub_off_t) -1)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 237b2aa77..f3e293a9e 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -536,7 +536,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 
 static grub_err_t
 luks2_recover_key (grub_disk_t source, grub_cryptodisk_t crypt,
-		   grub_file_t hdr_file)
+		   grub_file_t hdr_file, grub_uint8_t *key,
+		   grub_size_t keyfile_size)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
   char passphrase[MAX_PASSPHRASE], cipher[32];
@@ -550,8 +551,8 @@ luks2_recover_key (grub_disk_t source, grub_cryptodisk_t crypt,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  /* Detached headers are not implemented yet */
-  if (hdr_file)
+  /* Detached headers and keyfiles are not implemented yet */
+  if (hdr_file || key || keyfile_size)
     return GRUB_ERR_NOT_IMPLEMENTED_YET;
 
   ret = luks2_read_header (source, &header);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index d6f2f6e2c..572dbc782 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
@@ -115,7 +117,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_file_t hdr, grub_uint8_t *key,
+			     grub_size_t keyfile_size);
 };
 typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
 
diff --git a/include/grub/file.h b/include/grub/file.h
index a7d7be853..97678aa45 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -92,6 +92,8 @@ enum grub_file_type
     GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
     /* File holiding the encryption metadata header */
     GRUB_FILE_TYPE_CRYPTODISK_DETACHED_HEADER,
+    /* File holiding the encryption key */
+    GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY,
     /* File we open n grub-fstest.  */
     GRUB_FILE_TYPE_FSTEST,
     /* File we open n grub-mount.  */
-- 
2.29.2



  parent reply	other threads:[~2020-12-10  9:17 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-10  9:14 v7 for detached headers and key files Denis 'GNUtoo' Carikli
2020-12-10  9:14 ` [PATCH v7 1/6] cryptodisk: luks: unify grub_cryptodisk_dev function names Denis 'GNUtoo' Carikli
2020-12-10  9:14 ` [PATCH v7 2/6] cryptodisk: geli: " Denis 'GNUtoo' Carikli
2020-12-10  9:14 ` [PATCH v7 3/6] cryptodisk: enable the backends to implement detached headers Denis 'GNUtoo' Carikli
2020-12-10  9:14 ` [PATCH v7 4/6] cryptodisk: add support for LUKS1 " Denis 'GNUtoo' Carikli
2020-12-10  9:14 ` Denis 'GNUtoo' Carikli [this message]
2020-12-10  9:14 ` [PATCH v7 6/6] cryptodisk: Add support for LUKS1 key files Denis 'GNUtoo' Carikli
2020-12-16 18:35 ` v7 for detached headers and " Glenn Washburn
2020-12-17  0:27   ` Denis 'GNUtoo' Carikli
2021-08-17 22:30 ` Denis 'GNUtoo' Carikli
2021-08-26 18:06   ` Daniel Kiper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201210091459.11154-6-GNUtoo@cyberdimension.org \
    --to=gnutoo@cyberdimension.org \
    --cc=daniel.kiper@oracle.com \
    --cc=development@efficientek.com \
    --cc=grub-devel@gnu.org \
    --cc=john@lane.uk.net \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.