All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Cryptodisk fixes for v2.06 redux
@ 2020-10-03 21:45 Glenn Washburn
  2020-10-03 21:45 ` [PATCH 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
                   ` (10 more replies)
  0 siblings, 11 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This series is meant to address concerns Daniel had for patches 3, 4, 8, and 9
of Daniel's series with subject "[PATCH 0/9] Cryptodisk fixes for v2.06". These
were patches authored by me and which Daniel handed back for me to take the lead
in getting accepted. This series warrants a new thread because several patches
were split and new patches have been added to addresses suggestions from Daniel.

The comments from Daniel can be seen in the following ML messages:
  3: https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00071.html
  4: https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00070.html
  8: https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00021.html
  9: https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00069.html

Patches 1 and 2 are equivalent to patch 3 of the previous series, which was
split into patch 1 which fixed the indexing and error message bugs and patch 2
which improves readability of the code. Patch 3 is new and related to patches
1 and 2. It uses the keyslot number that cryptsetup understand when displaying
the keyslot to the user.

Patch 4 has not changed from patch 4 of the previous series, except the adding
of a line in the commit mesage mentioning the removal of the empty statement.
Daniel's suggestion to rename total_length to total_sectors is implemented in
patch 8. The other two suggestions, handling partial LUKS2 sectors and
grub_strtoull() errors, I don't believe warrant action as I argued in more
detail here:
  https://lists.gnu.org/archive/html/grub-devel/2020-10/msg00020.html

Patch 5 has also not changed from the equivalent patch 8 of the previous series,
but a more detailed commit message has been added per Daniel's suggestion.

Patch 6, previously patch 9, has been updated to change how the IV is updated
for plain and plain64 modes. This change is functionally equivalent to the
previous patch, but more easy to understand. A comment has been added to aid
that end. Also, the commit message was changed to be less confusing.

Patch 7 comes out of a suggestion by Daniel in the previous patch 9. Some
numerical literals are replaced with macros to compute those values. The
appropriately named macros aid in understanding the code. Note: I have not
functionally tested this as it affects mostly geli encrypted volumes which are
on *BSD, which I do not use. The code compiles, and I expect it to work, but I
would appreciate any *BSD geli users to verify that this still works for them.

Patches 8, 9, and 10 make no functional changes to the code. They solely rename
some identifiers. Patch 8 as mentioned above, was suggested by Daniel. Patches
9 and 10 are in the same vein in that they aid in the understanding of the code
by more accurately describing what the identifiers represent.

Glenn Washburn (10):
  luks2: Fix use of incorrect index and some grub_error() messages.
  luks2: Improve readability in luks2_get_keyslot.
  luks2: Use more intuitive keyslot key instead of index when naming
    keyslot.
  luks2: grub_cryptodisk_t->total_length is the max number of device
    native sectors
  cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  cryptodisk: Properly handle non-512 byte sized sectors.
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt.
  cryptodisk: Rename total_length field in grub_cryptodisk_t to
    total_sectors.
  cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  luks2: Rename source disk variabled named 'disk' to 'source' as in
    luks.c.

 grub-core/disk/cryptodisk.c | 78 +++++++++++++++++++---------------
 grub-core/disk/geli.c       |  4 +-
 grub-core/disk/luks.c       |  9 ++--
 grub-core/disk/luks2.c      | 84 ++++++++++++++++++++-----------------
 include/grub/cryptodisk.h   | 18 ++++++--
 include/grub/types.h        |  3 ++
 6 files changed, 116 insertions(+), 80 deletions(-)

-- 
2.27.0



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

* [PATCH 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:45 ` [PATCH 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

When looping over the digests and segments, the loop variable is j, but the
variable i is used to index in the the digests and segments json array. The
variable i is the keyslot index. Similarly, there are several grub_error()
statements using the wrong index in constructing the error string.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 31d7166fc..2241e0312 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
   for (j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&digest, &digests, i) ||
+      if (grub_json_getchild (&digest, &digests, j) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
 
       if ((d->keyslots & (1 << idx)))
 	break;
     }
   if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (j = 0; j < size; j++)
+  for (i = j, j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&segment, &segments, i) ||
+      if (grub_json_getchild (&segment, &segments, j) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
 
       if ((d->segments & (1 << idx)))
 	break;
     }
   if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-10-03 21:45 ` [PATCH 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:45 ` [PATCH 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

Introduce new variables keyslot_key, digest_key, and segment_key which
represent the integer key of the item in the respective associative array
when looping over the array items. This replaces using a generically
named variable named "idx" used for all three values. The parameter "i"
is renamed to "keyslot_idx" and the loop variable "j" is renamed to "i".
Error messages now distinguish between indexes and keys.  The former
include "index" in the error string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2241e0312..c3cd63606 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,54 +255,55 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t i)
+		   const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
-  grub_size_t j, size;
-  grub_uint64_t idx;
+  grub_size_t i, size;
+  grub_uint64_t keyslot_key, digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
-      grub_json_getchild (&keyslot, &keyslots, i) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
+      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, i);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
       grub_json_getsize (&size, &digests))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
-  for (j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&digest, &digests, j) ||
+      if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << keyslot_key)))
 	break;
     }
-  if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
+  if (i == size)
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (i = j, j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&segment, &segments, j) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+      if (grub_json_getchild (&segment, &segments, i) ||
+	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << segment_key)))
 	break;
     }
-  if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
+  if (i == size)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", digest_key);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-10-03 21:45 ` [PATCH 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
  2020-10-03 21:45 ` [PATCH 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:45 ` [PATCH 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

Use the keyslot key value in the keyslot json array rather than the index of
the keyslot in the json array. This is less confusing for the end user. For
example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
using the password for slot 4 to unlock the device, the messages using the
index of the keyslot will mention keyslot 1 (its a zero-based index).
Furthermore,with this change the keyslot number will align with the number
used to reference the keyslot when using the --key-slot argument to
cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c3cd63606..7917e02cd 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,16 +255,16 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t keyslot_idx)
+		   grub_uint64_t *keyslot_key, const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t keyslot_key, digest_key, segment_key;
+  grub_uint64_t digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
+      grub_json_getuint64 (keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
@@ -281,11 +281,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << keyslot_key)))
+      if ((d->keyslots & (1 << *keyslot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", *keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -593,17 +593,18 @@ luks2_recover_key (grub_disk_t disk,
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
-      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
+      grub_uint64_t keyslot_key;
+      ret = luks2_get_keyslot (&keyslot, &digest, &segment, &keyslot_key, json, i);
       if (ret)
 	goto err;
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", keyslot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -619,7 +620,7 @@ luks2_recover_key (grub_disk_t disk,
       if (ret)
 	{
 	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+			keyslot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -627,7 +628,7 @@ luks2_recover_key (grub_disk_t disk,
       if (ret)
 	{
 	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+			keyslot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), keyslot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (2 preceding siblings ...)
  2020-10-03 21:45 ` [PATCH 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:45 ` [PATCH 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

The total_length field is named confusingly because length usually refers to
bytes, whereas in this case its really the total number of sectors on the
device. Also counter-intuitively, grub_disk_get_size returns the total
number of device native sectors sectors. We need to convert the sectors from
the size of the underlying device to the cryptodisk sector size. And
segment.size is in bytes which need to be converted to cryptodisk sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 7917e02cd..8e99a1820 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -424,7 +424,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -611,9 +611,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
+	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (3 preceding siblings ...)
  2020-10-03 21:45 ` [PATCH 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:45 ` [PATCH 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

When setting cipher IV mode, detection is done by prefix matching the
cipher IV mode part of the cipher mode string.  Since "plain" matches
"plain64", we must check for "plain64" first.  Otherwise, "plain64" will
be detected as "plain".

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/cryptodisk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 13af84dd1..a3d672f68 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -501,10 +501,10 @@ grub_cryptodisk_setcipher (grub_cryptodisk_t crypt, const char *ciphername, cons
 
   if (cipheriv == NULL)
       ;
-  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
       mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
     {
       if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
-- 
2.27.0



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

* [PATCH 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (4 preceding siblings ...)
  2020-10-03 21:45 ` [PATCH 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
@ 2020-10-03 21:45 ` Glenn Washburn
  2020-10-03 21:46 ` [PATCH 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index a3d672f68..623f0f396 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
+	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 59702067a..20cc20b9b 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
   newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 8e99a1820..054d5455d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -499,7 +499,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index e1b21e785..006f3ec49 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (5 preceding siblings ...)
  2020-10-03 21:45 ` [PATCH 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-10-03 21:46 ` Glenn Washburn
  2020-10-03 21:46 ` [PATCH 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:46 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 12 +++++++-----
 include/grub/types.h        |  3 +++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 623f0f396..1a91c2d55 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  /* The IV is the 64 bit byte offset of the sector. */
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
+					       - log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_MAX(iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528..8b4267ebd 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
 
 #define GRUB_CHAR_BIT 8
 
+#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
+#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)
+
 #endif /* ! GRUB_TYPES_HEADER */
-- 
2.27.0



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

* [PATCH 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (6 preceding siblings ...)
  2020-10-03 21:46 ` [PATCH 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-10-03 21:46 ` Glenn Washburn
  2020-10-03 21:46 ` [PATCH 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:46 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes the creates an alignment with grub_disk_t naming of the same
field and is more intuitive as to how it should be used.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 2 +-
 grub-core/disk/geli.c       | 2 +-
 grub-core/disk/luks.c       | 2 +-
 grub-core/disk/luks2.c      | 4 ++--
 include/grub/cryptodisk.h   | 3 ++-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 1a91c2d55..f5d098f65 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -711,7 +711,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
     }
 
   disk->data = dev;
-  disk->total_sectors = dev->total_length;
+  disk->total_sectors = dev->total_sectors;
   disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
   disk->id = dev->id;
   dev->ref++;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d23299a..4ec875821 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_length = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = 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;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 20cc20b9b..545734342 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 054d5455d..995b413cd 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -616,10 +616,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
 			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 006f3ec49..9e10ae927 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -73,7 +73,8 @@ struct grub_cryptodisk
 
   char *source;
   grub_disk_addr_t offset;
-  grub_disk_addr_t total_length;
+  /* Total number of encrypted sectors of size (1<<log_sector_size) */
+  grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
   int ref;
   grub_crypto_cipher_handle_t cipher;
-- 
2.27.0



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

* [PATCH 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (7 preceding siblings ...)
  2020-10-03 21:46 ` [PATCH 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-10-03 21:46 ` Glenn Washburn
  2020-10-03 21:46 ` [PATCH 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:46 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes it clear that the offset represents sectors, not bytes, in order
to improve readability.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 10 +++++-----
 grub-core/disk/geli.c       |  2 +-
 grub-core/disk/luks.c       |  4 ++--
 grub-core/disk/luks2.c      |  4 ++--
 include/grub/cryptodisk.h   |  7 ++++++-
 5 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f5d098f65..64a51165c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -766,10 +766,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   err = grub_disk_read (dev->source_disk,
-			grub_disk_from_native_sector (disk, sector + dev->offset),
+			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
 			0, size << disk->log_sector_size, buf);
   if (err)
     {
@@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
@@ -827,7 +827,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
     }
 
   /* Since ->write was called so disk.mod is loaded but be paranoid  */
-  sector = sector + dev->offset;
+  sector = sector + dev->offset_sectors;
   if (grub_disk_write_weak)
     err = grub_disk_write_weak (dev->source_disk,
 				grub_disk_from_native_sector (disk, sector),
@@ -1240,7 +1240,7 @@ luks_script_get (grub_size_t *sz)
 	ptr = grub_stpcpy (ptr, "luks_mount ");
 	ptr = grub_stpcpy (ptr, i->uuid);
 	*ptr++ = ' ';
-	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
+	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
 	while (*ptr)
 	  ptr++;
 	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 4ec875821..0175ce4c4 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     }
   newdev->cipher = cipher;
   newdev->secondary_cipher = secondary_cipher;
-  newdev->offset = 0;
+  newdev->offset_sectors = 0;
   newdev->source_disk = NULL;
   newdev->benbi_log = 0;
   if (grub_le_to_cpu16 (header.alg) == 0x16)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 545734342..88f2da493 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
       return NULL;
-  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
+  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 995b413cd..01474d60c 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -612,12 +612,12 @@ luks2_recover_key (grub_disk_t disk,
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
 
       /* Set up disk according to keyslot's segment. */
-      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
+      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
 	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
-			       - crypt->offset;
+			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 9e10ae927..c8eef2204 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -72,7 +72,12 @@ struct grub_cryptodisk
   struct grub_cryptodisk **prev;
 
   char *source;
-  grub_disk_addr_t offset;
+
+  /*
+   * The number of sectors the start of the encrypted data is offset into the
+   * underlying disk, where sectors are the size noted by log_sector_size.
+   */
+  grub_disk_addr_t offset_sectors;
   /* Total number of encrypted sectors of size (1<<log_sector_size) */
   grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
-- 
2.27.0



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

* [PATCH 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (8 preceding siblings ...)
  2020-10-03 21:46 ` [PATCH 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-10-03 21:46 ` Glenn Washburn
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 21:46 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes it more obvious to the reader that the disk referred to is the
source disk, as opposed to say the disk holding the cryptodisk.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 01474d60c..c7f2f3405 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -416,7 +416,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
 
 static grub_err_t
 luks2_decrypt_key (grub_uint8_t *out_key,
-		   grub_disk_t disk, grub_cryptodisk_t crypt,
+		   grub_disk_t source, grub_cryptodisk_t crypt,
 		   grub_luks2_keyslot_t *k,
 		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
 {
@@ -492,7 +492,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
     }
 
   grub_errno = GRUB_ERR_NONE;
-  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
+  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
   if (ret)
     {
       grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
@@ -536,7 +536,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 }
 
 static grub_err_t
-luks2_recover_key (grub_disk_t disk,
+luks2_recover_key (grub_disk_t source,
 		   grub_cryptodisk_t crypt)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
@@ -551,7 +551,7 @@ luks2_recover_key (grub_disk_t disk,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  ret = luks2_read_header (disk, &header);
+  ret = luks2_read_header (source, &header);
   if (ret)
     return ret;
 
@@ -560,7 +560,7 @@ luks2_recover_key (grub_disk_t disk,
       return GRUB_ERR_OUT_OF_MEMORY;
 
   /* Read the JSON area. */
-  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
+  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
 			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
   if (ret)
       goto err;
@@ -577,10 +577,10 @@ luks2_recover_key (grub_disk_t disk,
     }
 
   /* Get the passphrase from the user. */
-  if (disk->partition)
-    part = grub_partition_get_name (disk->partition);
-  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
-		disk->partition ? "," : "", part ? : "",
+  if (source->partition)
+    part = grub_partition_get_name (source->partition);
+  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+		source->partition ? "," : "", part ? : "",
 		crypt->uuid);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     {
@@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
 			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
-      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
+      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-- 
2.27.0



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

* [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux
  2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                   ` (9 preceding siblings ...)
  2020-10-03 21:46 ` [PATCH 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-10-03 22:55 ` Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
                     ` (10 more replies)
  10 siblings, 11 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This is a minor update to fix patch 3, where I missed updating the format string
type code. This was causing i386 builds to fail. Rangediff is included.

Glenn Washburn (10):
  luks2: Fix use of incorrect index and some grub_error() messages.
  luks2: Improve readability in luks2_get_keyslot.
  luks2: Use more intuitive keyslot key instead of index when naming
    keyslot.
  luks2: grub_cryptodisk_t->total_length is the max number of device
    native sectors
  cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  cryptodisk: Properly handle non-512 byte sized sectors.
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt.
  cryptodisk: Rename total_length field in grub_cryptodisk_t to
    total_sectors.
  cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  luks2: Rename source disk variabled named 'disk' to 'source' as in
    luks.c.

 grub-core/disk/cryptodisk.c | 78 ++++++++++++++++++--------------
 grub-core/disk/geli.c       |  4 +-
 grub-core/disk/luks.c       |  9 ++--
 grub-core/disk/luks2.c      | 88 ++++++++++++++++++++-----------------
 include/grub/cryptodisk.h   | 18 ++++++--
 include/grub/types.h        |  3 ++
 6 files changed, 118 insertions(+), 82 deletions(-)

Range-diff against v1:
1:  00646c92f ! 1:  e2433b8ab luks2: Use more intuitive keyslot key instead of index when naming keyslot.
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
            if (keyslot.priority == 0)
      	{
     -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
    -+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", keyslot_key);
    ++	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key);
      	  continue;
              }
      
     -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
    -+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
    ++      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
      
            /* Set up disk according to keyslot's segment. */
            crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    + 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
            if (ret)
      	{
    - 	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
    +-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
     -			i, grub_errmsg);
    ++	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
     +			keyslot_key, grub_errmsg);
      	  continue;
      	}
      
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    +       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
            if (ret)
      	{
    - 	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
    +-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
     -			i, grub_errmsg);
    ++	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
     +			keyslot_key, grub_errmsg);
      	  continue;
      	}
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
             * where each element is either empty or holds a key.
             */
     -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
    -+      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), keyslot_key);
    ++      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot_key);
      
            candidate_key_len = keyslot.key_size;
            break;
2:  137909929 = 2:  3baffdd4f luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
3:  9cfbb3373 = 3:  6da3d8598 cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
4:  5f7bd00a6 = 4:  fd7cb6b16 cryptodisk: Properly handle non-512 byte sized sectors.
5:  4251c828a = 5:  b33733199 cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
6:  feb8298b8 = 6:  de4f6b2e5 cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
7:  e26aed2ee ! 7:  a165791de cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
    @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
    +       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
      
            /* Set up disk according to keyslot's segment. */
     -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
8:  e083b25e2 = 8:  86beb5be8 luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
-- 
2.27.0



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

* [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:38     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
                     ` (9 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

When looping over the digests and segments, the loop variable is j, but the
variable i is used to index in the the digests and segments json array. The
variable i is the keyslot index. Similarly, there are several grub_error()
statements using the wrong index in constructing the error string.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 31d7166fc..2241e0312 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
   for (j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&digest, &digests, i) ||
+      if (grub_json_getchild (&digest, &digests, j) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
 
       if ((d->keyslots & (1 << idx)))
 	break;
     }
   if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (j = 0; j < size; j++)
+  for (i = j, j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&segment, &segments, i) ||
+      if (grub_json_getchild (&segment, &segments, j) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
 
       if ((d->segments & (1 << idx)))
 	break;
     }
   if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH v2 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

Introduce new variables keyslot_key, digest_key, and segment_key which
represent the integer key of the item in the respective associative array
when looping over the array items. This replaces using a generically
named variable named "idx" used for all three values. The parameter "i"
is renamed to "keyslot_idx" and the loop variable "j" is renamed to "i".
Error messages now distinguish between indexes and keys.  The former
include "index" in the error string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2241e0312..c3cd63606 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,54 +255,55 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t i)
+		   const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
-  grub_size_t j, size;
-  grub_uint64_t idx;
+  grub_size_t i, size;
+  grub_uint64_t keyslot_key, digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
-      grub_json_getchild (&keyslot, &keyslots, i) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
+      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, i);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
       grub_json_getsize (&size, &digests))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
-  for (j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&digest, &digests, j) ||
+      if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << keyslot_key)))
 	break;
     }
-  if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
+  if (i == size)
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (i = j, j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&segment, &segments, j) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+      if (grub_json_getchild (&segment, &segments, i) ||
+	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << segment_key)))
 	break;
     }
-  if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
+  if (i == size)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", digest_key);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:44     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
                     ` (7 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

Use the keyslot key value in the keyslot json array rather than the index of
the keyslot in the json array. This is less confusing for the end user. For
example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
using the password for slot 4 to unlock the device, the messages using the
index of the keyslot will mention keyslot 1 (its a zero-based index).
Furthermore,with this change the keyslot number will align with the number
used to reference the keyslot when using the --key-slot argument to
cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c3cd63606..db251cce0 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,16 +255,16 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t keyslot_idx)
+		   grub_uint64_t *keyslot_key, const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t keyslot_key, digest_key, segment_key;
+  grub_uint64_t digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
+      grub_json_getuint64 (keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
@@ -281,11 +281,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << keyslot_key)))
+      if ((d->keyslots & (1 << *keyslot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", *keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -593,17 +593,18 @@ luks2_recover_key (grub_disk_t disk,
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
-      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
+      grub_uint64_t keyslot_key;
+      ret = luks2_get_keyslot (&keyslot, &digest, &segment, &keyslot_key, json, i);
       if (ret)
 	goto err;
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -618,16 +619,16 @@ luks2_recover_key (grub_disk_t disk,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
+			keyslot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
+			keyslot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (2 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:45     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

The total_length field is named confusingly because length usually refers to
bytes, whereas in this case its really the total number of sectors on the
device. Also counter-intuitively, grub_disk_get_size returns the total
number of device native sectors sectors. We need to convert the sectors from
the size of the underlying device to the cryptodisk sector size. And
segment.size is in bytes which need to be converted to cryptodisk sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index db251cce0..9f7d6e12b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -424,7 +424,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -611,9 +611,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
+	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v2 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (3 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

When setting cipher IV mode, detection is done by prefix matching the
cipher IV mode part of the cipher mode string.  Since "plain" matches
"plain64", we must check for "plain64" first.  Otherwise, "plain64" will
be detected as "plain".

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/cryptodisk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 13af84dd1..a3d672f68 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -501,10 +501,10 @@ grub_cryptodisk_setcipher (grub_cryptodisk_t crypt, const char *ciphername, cons
 
   if (cipheriv == NULL)
       ;
-  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
       mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
     {
       if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
-- 
2.27.0



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

* [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (4 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:50     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                     ` (4 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index a3d672f68..623f0f396 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
+	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 59702067a..20cc20b9b 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
   newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 9f7d6e12b..b7d3b425a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -499,7 +499,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index e1b21e785..006f3ec49 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (5 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-18 18:23     ` Glenn Washburn
  2020-10-03 22:55   ` [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 12 +++++++-----
 include/grub/types.h        |  3 +++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 623f0f396..1a91c2d55 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  /* The IV is the 64 bit byte offset of the sector. */
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
+					       - log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_MAX(iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528..8b4267ebd 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
 
 #define GRUB_CHAR_BIT 8
 
+#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
+#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)
+
 #endif /* ! GRUB_TYPES_HEADER */
-- 
2.27.0



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

* [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (6 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:55     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
                     ` (2 subsequent siblings)
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes the creates an alignment with grub_disk_t naming of the same
field and is more intuitive as to how it should be used.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 2 +-
 grub-core/disk/geli.c       | 2 +-
 grub-core/disk/luks.c       | 2 +-
 grub-core/disk/luks2.c      | 4 ++--
 include/grub/cryptodisk.h   | 3 ++-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 1a91c2d55..f5d098f65 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -711,7 +711,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
     }
 
   disk->data = dev;
-  disk->total_sectors = dev->total_length;
+  disk->total_sectors = dev->total_sectors;
   disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
   disk->id = dev->id;
   dev->ref++;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d23299a..4ec875821 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_length = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = 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;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 20cc20b9b..545734342 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index b7d3b425a..2e295cac8 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -616,10 +616,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
 			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 006f3ec49..9e10ae927 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -73,7 +73,8 @@ struct grub_cryptodisk
 
   char *source;
   grub_disk_addr_t offset;
-  grub_disk_addr_t total_length;
+  /* Total number of encrypted sectors of size (1<<log_sector_size) */
+  grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
   int ref;
   grub_crypto_cipher_handle_t cipher;
-- 
2.27.0



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

* [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (7 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09  9:56     ` Patrick Steinhardt
  2020-10-03 22:55   ` [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
  2020-10-09 10:01   ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes it clear that the offset represents sectors, not bytes, in order
to improve readability.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 10 +++++-----
 grub-core/disk/geli.c       |  2 +-
 grub-core/disk/luks.c       |  4 ++--
 grub-core/disk/luks2.c      |  4 ++--
 include/grub/cryptodisk.h   |  7 ++++++-
 5 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f5d098f65..64a51165c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -766,10 +766,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   err = grub_disk_read (dev->source_disk,
-			grub_disk_from_native_sector (disk, sector + dev->offset),
+			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
 			0, size << disk->log_sector_size, buf);
   if (err)
     {
@@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
@@ -827,7 +827,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
     }
 
   /* Since ->write was called so disk.mod is loaded but be paranoid  */
-  sector = sector + dev->offset;
+  sector = sector + dev->offset_sectors;
   if (grub_disk_write_weak)
     err = grub_disk_write_weak (dev->source_disk,
 				grub_disk_from_native_sector (disk, sector),
@@ -1240,7 +1240,7 @@ luks_script_get (grub_size_t *sz)
 	ptr = grub_stpcpy (ptr, "luks_mount ");
 	ptr = grub_stpcpy (ptr, i->uuid);
 	*ptr++ = ' ';
-	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
+	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
 	while (*ptr)
 	  ptr++;
 	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 4ec875821..0175ce4c4 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     }
   newdev->cipher = cipher;
   newdev->secondary_cipher = secondary_cipher;
-  newdev->offset = 0;
+  newdev->offset_sectors = 0;
   newdev->source_disk = NULL;
   newdev->benbi_log = 0;
   if (grub_le_to_cpu16 (header.alg) == 0x16)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 545734342..88f2da493 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
       return NULL;
-  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
+  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2e295cac8..46abc96ef 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -612,12 +612,12 @@ luks2_recover_key (grub_disk_t disk,
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
 
       /* Set up disk according to keyslot's segment. */
-      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
+      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
 	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
-			       - crypt->offset;
+			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 9e10ae927..c8eef2204 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -72,7 +72,12 @@ struct grub_cryptodisk
   struct grub_cryptodisk **prev;
 
   char *source;
-  grub_disk_addr_t offset;
+
+  /*
+   * The number of sectors the start of the encrypted data is offset into the
+   * underlying disk, where sectors are the size noted by log_sector_size.
+   */
+  grub_disk_addr_t offset_sectors;
   /* Total number of encrypted sectors of size (1<<log_sector_size) */
   grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
-- 
2.27.0



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

* [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (8 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-10-03 22:55   ` Glenn Washburn
  2020-10-09 10:00     ` Patrick Steinhardt
  2020-10-09 10:01   ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
  10 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-03 22:55 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt, Glenn Washburn

This makes it more obvious to the reader that the disk referred to is the
source disk, as opposed to say the disk holding the cryptodisk.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 46abc96ef..f918f5a52 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -416,7 +416,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
 
 static grub_err_t
 luks2_decrypt_key (grub_uint8_t *out_key,
-		   grub_disk_t disk, grub_cryptodisk_t crypt,
+		   grub_disk_t source, grub_cryptodisk_t crypt,
 		   grub_luks2_keyslot_t *k,
 		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
 {
@@ -492,7 +492,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
     }
 
   grub_errno = GRUB_ERR_NONE;
-  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
+  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
   if (ret)
     {
       grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
@@ -536,7 +536,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 }
 
 static grub_err_t
-luks2_recover_key (grub_disk_t disk,
+luks2_recover_key (grub_disk_t source,
 		   grub_cryptodisk_t crypt)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
@@ -551,7 +551,7 @@ luks2_recover_key (grub_disk_t disk,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  ret = luks2_read_header (disk, &header);
+  ret = luks2_read_header (source, &header);
   if (ret)
     return ret;
 
@@ -560,7 +560,7 @@ luks2_recover_key (grub_disk_t disk,
       return GRUB_ERR_OUT_OF_MEMORY;
 
   /* Read the JSON area. */
-  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
+  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
 			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
   if (ret)
       goto err;
@@ -577,10 +577,10 @@ luks2_recover_key (grub_disk_t disk,
     }
 
   /* Get the passphrase from the user. */
-  if (disk->partition)
-    part = grub_partition_get_name (disk->partition);
-  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
-		disk->partition ? "," : "", part ? : "",
+  if (source->partition)
+    part = grub_partition_get_name (source->partition);
+  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+		source->partition ? "," : "", part ? : "",
 		crypt->uuid);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     {
@@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
 			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
-      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
+      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-- 
2.27.0



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

* Re: [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-03 22:55   ` [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
@ 2020-10-09  9:38     ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:38 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:25PM -0500, Glenn Washburn wrote:
> When looping over the digests and segments, the loop variable is j, but the
> variable i is used to index in the the digests and segments json array. The
> variable i is the keyslot index. Similarly, there are several grub_error()
> statements using the wrong index in constructing the error string.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 31d7166fc..2241e0312 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
>    for (j = 0; j < size; j++)
>      {
> -      if (grub_json_getchild (&digest, &digests, i) ||
> +      if (grub_json_getchild (&digest, &digests, j) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
>  
>        if ((d->keyslots & (1 << idx)))
>  	break;
>      }
>    if (j == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
>        grub_json_getsize (&size, &segments))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
> -  for (j = 0; j < size; j++)
> +  for (i = j, j = 0; j < size; j++)
>      {
> -      if (grub_json_getchild (&segment, &segments, i) ||
> +      if (grub_json_getchild (&segment, &segments, j) ||
>  	  grub_json_getuint64 (&idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
>  
>        if ((d->segments & (1 << idx)))
>  	break;
>      }
>    if (j == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
>  
>    return GRUB_ERR_NONE;
>  }
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-03 22:55   ` [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-10-09  9:44     ` Patrick Steinhardt
  2020-10-18 19:05       ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:44 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:27PM -0500, Glenn Washburn wrote:
> Use the keyslot key value in the keyslot json array rather than the index of
> the keyslot in the json array. This is less confusing for the end user. For
> example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
> using the password for slot 4 to unlock the device, the messages using the
> index of the keyslot will mention keyslot 1 (its a zero-based index).
> Furthermore,with this change the keyslot number will align with the number
> used to reference the keyslot when using the --key-slot argument to
> cryptsetup.

The rationale does make sense to me, but I'm not sure I like cramming
this information into another out-parameter. The result feels a bit hard
to read to me and is not immediately obvious. How about we instead add
another member "index" or similar to `struct grub_luks2_keyslot`?

Patrick

> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 27 ++++++++++++++-------------
>  1 file changed, 14 insertions(+), 13 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index c3cd63606..db251cce0 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -255,16 +255,16 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>  
>  static grub_err_t
>  luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
> -		   const grub_json_t *root, grub_size_t keyslot_idx)
> +		   grub_uint64_t *keyslot_key, const grub_json_t *root, grub_size_t keyslot_idx)
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t keyslot_key, digest_key, segment_key;
> +  grub_uint64_t digest_key, segment_key;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> +      grub_json_getuint64 (keyslot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -281,11 +281,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>            luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << keyslot_key)))
> +      if ((d->keyslots & (1 << *keyslot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", *keyslot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -593,17 +593,18 @@ luks2_recover_key (grub_disk_t disk,
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> -      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
> +      grub_uint64_t keyslot_key;
> +      ret = luks2_get_keyslot (&keyslot, &digest, &segment, &keyslot_key, json, i);
>        if (ret)
>  	goto err;
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key);
>  	  continue;
>          }
>  
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -618,16 +619,16 @@ luks2_recover_key (grub_disk_t disk,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
> +			keyslot_key, grub_errmsg);
>  	  continue;
>  	}
>  
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
> +			keyslot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot_key);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-10-03 22:55   ` [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-10-09  9:45     ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:45 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:28PM -0500, Glenn Washburn wrote:
> The total_length field is named confusingly because length usually refers to
> bytes, whereas in this case its really the total number of sectors on the
> device. Also counter-intuitively, grub_disk_get_size returns the total
> number of device native sectors sectors. We need to convert the sectors from
                          ^~~~~~~~~~~~~~~

Nit: there's a duplicate word here.

Patrick

> the size of the underlying device to the cryptodisk sector size. And
> segment.size is in bytes which need to be converted to cryptodisk sectors.
> 
> Also, removed an empty statement.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index db251cce0..9f7d6e12b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -424,7 +424,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>    grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
>    grub_uint8_t *split_key = NULL;
>    grub_size_t saltlen = sizeof (salt);
> -  char cipher[32], *p;;
> +  char cipher[32], *p;
>    const gcry_md_spec_t *hash;
>    gcry_err_code_t gcry_ret;
>    grub_err_t ret;
> @@ -611,9 +611,10 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
> +	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +			       - crypt->offset;
>        else
> -	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-03 22:55   ` [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-10-09  9:50     ` Patrick Steinhardt
  2020-10-18 18:38       ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:50 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:30PM -0500, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
> 
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
> 
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 47 insertions(+), 25 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index a3d672f68..623f0f396 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>  
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>  
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> +	      iv[1] = 0;

I may be misreading this, but aren't we zeroing out 64 bits here instead
of 32 bits as the comment states?

Patrick

> +	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> +	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>  				    & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> @@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_CBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_PCBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (err)
>  	      return err;
>  	    
> -	    for (j = 0; j < (1U << dev->log_sector_size);
> +	    for (j = 0; j < (1U << log_sector_size);
>  		 j += dev->cipher->cipher->blocksize)
>  	      {
>  		grub_crypto_xor (data + i + j, data + i + j, iv,
> @@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (do_encrypt)
>  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    else
>  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    if (err)
>  	      return err;
>  	    lrw_xor (&sec, dev, data + i);
> @@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_ECB:
>  	  if (do_encrypt)
>  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  else
>  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector)
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
>  {
> -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
>  }
>  
>  grub_err_t
> @@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
>  					size << disk->log_sector_size,
> -					sector, 0);
> +					sector, dev->log_sector_size, 0);
>    return grub_crypto_gcry_error (gcry_err);
>  }
>  
> @@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> -					sector, 1);
> +					sector, disk->log_sector_size, 1);
>    if (gcry_err)
>      {
>        grub_free (tmp);
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 59702067a..20cc20b9b 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
> -  newdev->log_sector_size = 9;
> +  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
>    newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
> @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
>  	  return err;
>  	}
>  
> -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> +					  LUKS1_LOG_SECTOR_SIZE);
>        if (gcry_err)
>  	{
>  	  grub_free (split_key);
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 9f7d6e12b..b7d3b425a 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -499,7 +499,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>        goto err;
>      }
>  
> -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> +  /*
> +   * The key slots area is always encrypted in 512-byte sectors,
> +   * regardless of encrypted data sector size.
> +   */
> +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> +				      LUKS1_LOG_SECTOR_SIZE);
>    if (gcry_ret)
>      {
>        ret = grub_crypto_gcry_error (gcry_ret);
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index e1b21e785..006f3ec49 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -48,6 +48,12 @@ typedef enum
>  
>  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
>  
> +/* LUKS1 specification defines the block size to always be 512 bytes. */
> +#define LUKS1_LOG_SECTOR_SIZE 9
> +
> +/* By default dm-crypt increments the IV every 512 bytes. */
> +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> +
>  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
>  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
> @@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector);
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size);
>  grub_err_t
>  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
>  			grub_disk_t source);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-03 22:55   ` [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-10-09  9:55     ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:55 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:32PM -0500, Glenn Washburn wrote:
> This makes the creates an alignment with grub_disk_t naming of the same
> field and is more intuitive as to how it should be used.

> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---

There's something off with the commit message here. Other than that:

Reviewed-by: Patrick Steinhardt <ps@pks.im>

>  grub-core/disk/cryptodisk.c | 2 +-
>  grub-core/disk/geli.c       | 2 +-
>  grub-core/disk/luks.c       | 2 +-
>  grub-core/disk/luks2.c      | 4 ++--
>  include/grub/cryptodisk.h   | 3 ++-
>  5 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 1a91c2d55..f5d098f65 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -711,7 +711,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
>      }
>  
>    disk->data = dev;
> -  disk->total_sectors = dev->total_length;
> +  disk->total_sectors = dev->total_sectors;
>    disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
>    disk->id = dev->id;
>    dev->ref++;
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index e9d23299a..4ec875821 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>  
>    newdev->modname = "geli";
>  
> -  newdev->total_length = grub_disk_get_size (disk) - 1;
> +  newdev->total_sectors = 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;
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 20cc20b9b..545734342 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> -  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index b7d3b425a..2e295cac8 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -616,10 +616,10 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
>  			       - crypt->offset;
>        else
> -	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 006f3ec49..9e10ae927 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -73,7 +73,8 @@ struct grub_cryptodisk
>  
>    char *source;
>    grub_disk_addr_t offset;
> -  grub_disk_addr_t total_length;
> +  /* Total number of encrypted sectors of size (1<<log_sector_size) */
> +  grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
>    int ref;
>    grub_crypto_cipher_handle_t cipher;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-03 22:55   ` [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-10-09  9:56     ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09  9:56 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:33PM -0500, Glenn Washburn wrote:
> This makes it clear that the offset represents sectors, not bytes, in order
> to improve readability.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 10 +++++-----
>  grub-core/disk/geli.c       |  2 +-
>  grub-core/disk/luks.c       |  4 ++--
>  grub-core/disk/luks2.c      |  4 ++--
>  include/grub/cryptodisk.h   |  7 ++++++-
>  5 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index f5d098f65..64a51165c 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -766,10 +766,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    err = grub_disk_read (dev->source_disk,
> -			grub_disk_from_native_sector (disk, sector + dev->offset),
> +			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
>  			0, size << disk->log_sector_size, buf);
>    if (err)
>      {
> @@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> @@ -827,7 +827,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>  
>    /* Since ->write was called so disk.mod is loaded but be paranoid  */
> -  sector = sector + dev->offset;
> +  sector = sector + dev->offset_sectors;
>    if (grub_disk_write_weak)
>      err = grub_disk_write_weak (dev->source_disk,
>  				grub_disk_from_native_sector (disk, sector),
> @@ -1240,7 +1240,7 @@ luks_script_get (grub_size_t *sz)
>  	ptr = grub_stpcpy (ptr, "luks_mount ");
>  	ptr = grub_stpcpy (ptr, i->uuid);
>  	*ptr++ = ' ';
> -	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
> +	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
>  	while (*ptr)
>  	  ptr++;
>  	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index 4ec875821..0175ce4c4 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>      }
>    newdev->cipher = cipher;
>    newdev->secondary_cipher = secondary_cipher;
> -  newdev->offset = 0;
> +  newdev->offset_sectors = 0;
>    newdev->source_disk = NULL;
>    newdev->benbi_log = 0;
>    if (grub_le_to_cpu16 (header.alg) == 0x16)
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 545734342..88f2da493 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
>    if (!newdev)
>        return NULL;
> -  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> +  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> -  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 2e295cac8..46abc96ef 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -612,12 +612,12 @@ luks2_recover_key (grub_disk_t disk,
>        grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
>  
>        /* Set up disk according to keyslot's segment. */
> -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> +      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
>  	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> -			       - crypt->offset;
> +			       - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 9e10ae927..c8eef2204 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -72,7 +72,12 @@ struct grub_cryptodisk
>    struct grub_cryptodisk **prev;
>  
>    char *source;
> -  grub_disk_addr_t offset;
> +
> +  /*
> +   * The number of sectors the start of the encrypted data is offset into the
> +   * underlying disk, where sectors are the size noted by log_sector_size.
> +   */
> +  grub_disk_addr_t offset_sectors;
>    /* Total number of encrypted sectors of size (1<<log_sector_size) */
>    grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-03 22:55   ` [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-10-09 10:00     ` Patrick Steinhardt
  2020-10-19 16:27       ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09 10:00 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:34PM -0500, Glenn Washburn wrote:
> This makes it more obvious to the reader that the disk referred to is the
> source disk, as opposed to say the disk holding the cryptodisk.

Hum. I'm not sure this actually helps readability, mostly because I
think that the distinction here is not that helpful in the context of
encryption or decryption of the device. In the end we are trying to
encrypt or decrypt the disk in order to create the new cryptodisk.

Anyway, I don't particularly care, so take this just as my two cents.
The patch itself looks good to me.

Patrick

> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 46abc96ef..f918f5a52 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -416,7 +416,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
>  
>  static grub_err_t
>  luks2_decrypt_key (grub_uint8_t *out_key,
> -		   grub_disk_t disk, grub_cryptodisk_t crypt,
> +		   grub_disk_t source, grub_cryptodisk_t crypt,
>  		   grub_luks2_keyslot_t *k,
>  		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
>  {
> @@ -492,7 +492,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>      }
>  
>    grub_errno = GRUB_ERR_NONE;
> -  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
> +  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
>    if (ret)
>      {
>        grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
> @@ -536,7 +536,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>  }
>  
>  static grub_err_t
> -luks2_recover_key (grub_disk_t disk,
> +luks2_recover_key (grub_disk_t source,
>  		   grub_cryptodisk_t crypt)
>  {
>    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
> @@ -551,7 +551,7 @@ luks2_recover_key (grub_disk_t disk,
>    grub_json_t *json = NULL, keyslots;
>    grub_err_t ret;
>  
> -  ret = luks2_read_header (disk, &header);
> +  ret = luks2_read_header (source, &header);
>    if (ret)
>      return ret;
>  
> @@ -560,7 +560,7 @@ luks2_recover_key (grub_disk_t disk,
>        return GRUB_ERR_OUT_OF_MEMORY;
>  
>    /* Read the JSON area. */
> -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
> +  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
>  			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
>    if (ret)
>        goto err;
> @@ -577,10 +577,10 @@ luks2_recover_key (grub_disk_t disk,
>      }
>  
>    /* Get the passphrase from the user. */
> -  if (disk->partition)
> -    part = grub_partition_get_name (disk->partition);
> -  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
> -		disk->partition ? "," : "", part ? : "",
> +  if (source->partition)
> +    part = grub_partition_get_name (source->partition);
> +  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> +		source->partition ? "," : "", part ? : "",
>  		crypt->uuid);
>    if (!grub_password_get (passphrase, MAX_PASSPHRASE))
>      {
> @@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
>  			       - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
> -      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
> +      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux
  2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
                     ` (9 preceding siblings ...)
  2020-10-03 22:55   ` [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-10-09 10:01   ` Patrick Steinhardt
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
  10 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-09 10:01 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Sat, Oct 03, 2020 at 05:55:24PM -0500, Glenn Washburn wrote:
> This is a minor update to fix patch 3, where I missed updating the format string
> type code. This was causing i386 builds to fail. Rangediff is included.

Cool, thanks a lot for taking care of this! I've left a few comments
here and there, but overall things look good to me.

Patrick

> Glenn Washburn (10):
>   luks2: Fix use of incorrect index and some grub_error() messages.
>   luks2: Improve readability in luks2_get_keyslot.
>   luks2: Use more intuitive keyslot key instead of index when naming
>     keyslot.
>   luks2: grub_cryptodisk_t->total_length is the max number of device
>     native sectors
>   cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
>   cryptodisk: Properly handle non-512 byte sized sectors.
>   cryptodisk: Replace some literals with constants in
>     grub_cryptodisk_endecrypt.
>   cryptodisk: Rename total_length field in grub_cryptodisk_t to
>     total_sectors.
>   cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
>   luks2: Rename source disk variabled named 'disk' to 'source' as in
>     luks.c.
> 
>  grub-core/disk/cryptodisk.c | 78 ++++++++++++++++++--------------
>  grub-core/disk/geli.c       |  4 +-
>  grub-core/disk/luks.c       |  9 ++--
>  grub-core/disk/luks2.c      | 88 ++++++++++++++++++++-----------------
>  include/grub/cryptodisk.h   | 18 ++++++--
>  include/grub/types.h        |  3 ++
>  6 files changed, 118 insertions(+), 82 deletions(-)
> 
> Range-diff against v1:
> 1:  00646c92f ! 1:  e2433b8ab luks2: Use more intuitive keyslot key instead of index when naming keyslot.
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
>             if (keyslot.priority == 0)
>       	{
>      -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
>     -+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", keyslot_key);
>     ++	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key);
>       	  continue;
>               }
>       
>      -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
>     -+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
>     ++      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
>       
>             /* Set up disk according to keyslot's segment. */
>             crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
>     + 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>             if (ret)
>       	{
>     - 	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
>     +-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
>      -			i, grub_errmsg);
>     ++	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
>      +			keyslot_key, grub_errmsg);
>       	  continue;
>       	}
>       
>     -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
>     +       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>             if (ret)
>       	{
>     - 	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
>     +-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
>      -			i, grub_errmsg);
>     ++	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
>      +			keyslot_key, grub_errmsg);
>       	  continue;
>       	}
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
>              * where each element is either empty or holds a key.
>              */
>      -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
>     -+      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), keyslot_key);
>     ++      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot_key);
>       
>             candidate_key_len = keyslot.key_size;
>             break;
> 2:  137909929 = 2:  3baffdd4f luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
> 3:  9cfbb3373 = 3:  6da3d8598 cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
> 4:  5f7bd00a6 = 4:  fd7cb6b16 cryptodisk: Properly handle non-512 byte sized sectors.
> 5:  4251c828a = 5:  b33733199 cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
> 6:  feb8298b8 = 6:  de4f6b2e5 cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
> 7:  e26aed2ee ! 7:  a165791de cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
>     @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
>      
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
>     -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", keyslot_key);
>     +       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
>       
>             /* Set up disk according to keyslot's segment. */
>      -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> 8:  e083b25e2 = 8:  86beb5be8 luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-03 22:55   ` [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-10-18 18:23     ` Glenn Washburn
  2020-10-19 11:27       ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-18 18:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Daniel Kiper, Patrick Steinhardt

Daniel, Patrick,

Have either of you had a chance to review this patch?  Daniel, this is
my interpretation of what you suggested earlier to remove constant
literals in this message:
https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00069.html

I'm going to make a v3 patchset with Patrick's suggested changes.
Please reply to that patch.

Glenn

On Sat,  3 Oct 2020 17:55:31 -0500
Glenn Washburn <development@efficientek.com> wrote:

> This should improve readability of code by providing clues as to what
> the value represents.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 12 +++++++-----
>  include/grub/types.h        |  3 +++
>  2 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 623f0f396..1a91c2d55 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct
> grub_cryptodisk *dev, }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> log_sector_size));
> +	  /* The IV is the 64 bit byte offset of the sector. */
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
> +					       - log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_MAX(iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >>
> GRUB_TYPE_BIT(iv[0]));
> +	    iv[sz - 1] = grub_cpu_to_be32 (num &
> GRUB_TYPE_MAX(iv[0])); }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 035a4b528..8b4267ebd 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void
> *ptr, grub_uint64_t val) 
>  #define GRUB_CHAR_BIT 8
>  
> +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
> +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) -
> 1)) - 1)) + 1) +
>  #endif /* ! GRUB_TYPES_HEADER */


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

* Re: [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-09  9:50     ` Patrick Steinhardt
@ 2020-10-18 18:38       ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-18 18:38 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Fri, 9 Oct 2020 11:50:29 +0200
Patrick Steinhardt <ps@pks.im> wrote:

> On Sat, Oct 03, 2020 at 05:55:30PM -0500, Glenn Washburn wrote:
> > By default, dm-crypt internally uses an IV that corresponds to
> > 512-byte sectors, even when a larger sector size is specified. What
> > this means is that when using a larger sector size, the IV is
> > incremented every sector. However, the amount the IV is incremented
> > is the number of 512 byte blocks in a sector (ie 8 for 4K sectors).
> > Confusingly the IV does not corespond to the number of, for
> > example, 4K sectors. So each 512 byte cipher block in a sector will
> > be encrypted with the same IV and the IV will be incremented
> > afterwards by the number of 512 byte cipher blocks in the sector.
> > 
> > There are some encryption utilities which do it the intuitive way
> > and have the IV equal to the sector number regardless of sector
> > size (ie. the fifth sector would have an IV of 4 for each cipher
> > block). And this is supported by dm-crypt with the iv_large_sectors
> > option and also cryptsetup as of 2.3.3 with the --iv-large-sectors,
> > though not with LUKS headers (only with --type plain). However,
> > support for this has not been included as grub does not support
> > plain devices right now.
> > 
> > One gotcha here is that the encrypted split keys are encrypted with
> > a hard- coded 512-byte sector size. So even if your data is
> > encrypted with 4K sector sizes, the split key encrypted area must
> > be decrypted with a block size of 512 (ie the IV increments every
> > 512 bytes). This made these changes less aestetically pleasing than
> > desired.
> > 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 52
> > ++++++++++++++++++++++--------------- grub-core/disk/luks.c       |
> >  5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> >  include/grub/cryptodisk.h   |  8 +++++-
> >  4 files changed, 47 insertions(+), 25 deletions(-)
> > 
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> >  static gcry_err_code_t
> >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  			   grub_uint8_t * data, grub_size_t len,
> > -			   grub_disk_addr_t sector, int do_encrypt)
> > +			   grub_disk_addr_t sector, grub_size_t
> > log_sector_size,
> > +			   int do_encrypt)
> >  {
> >    grub_size_t i;
> >    gcry_err_code_t err;
> > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, return (do_encrypt ? grub_crypto_ecb_encrypt
> > (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt
> > (dev->cipher, data, data, len)); 
> > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > +  for (i = 0; i < len; i += (1U << log_sector_size))
> >      {
> >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> >  			 + sizeof (grub_uint32_t) - 1)
> > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (!ctx)
> >  	      return GPG_ERR_OUT_OF_MEMORY;
> >  
> > -	    tmp = grub_cpu_to_le64 (sector <<
> > dev->log_sector_size);
> > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> >  	    dev->iv_hash->init (ctx);
> >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > -	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  /*
> > +	   * The IV is a 32 or 64 bit value of the dm-crypt native
> > sector
> > +	   * number. If using 32 bit IV mode, zero out the most
> > significant
> > +	   * 32 bits.
> > +	   */
> > +	  {
> > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> > +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> > +						 -
> > GRUB_CRYPTODISK_IV_LOG_SIZE));
> > +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> > +	      iv[1] = 0;
> 
> I may be misreading this, but aren't we zeroing out 64 bits here
> instead of 32 bits as the comment states?
> 
> Patrick

We are only zeroing out 32bits because iv is declared as an array of
grub_uint32_t.  iv[1] will be the 32 right-most bits of iv64 (and
iv[0] the left-most 32 bits). Since iv64 is little-endian the right-most
32 bits will correspond to the most significant 32 bits of iv64.

> > +	  }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > dev->log_sector_size));
> > -	  iv[0] = grub_cpu_to_le32 ((sector <<
> > dev->log_sector_size)
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > log_sector_size));
> > +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> >  				    & 0xFFFFFFFF);
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> > @@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_CBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size), iv);
> > +					   (1U <<
> > log_sector_size), iv); else
> >  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size), iv);
> > +					   (1U <<
> > log_sector_size), iv); if (err)
> >  	    return err;
> >  	  break;
> > @@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_PCBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i,
> > data + i,
> > -					    (1U <<
> > dev->log_sector_size), iv);
> > +					    (1U <<
> > log_sector_size), iv); else
> >  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i,
> > data + i,
> > -					    (1U <<
> > dev->log_sector_size), iv);
> > +					    (1U <<
> > log_sector_size), iv); if (err)
> >  	    return err;
> >  	  break;
> > @@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (err)
> >  	      return err;
> >  	    
> > -	    for (j = 0; j < (1U << dev->log_sector_size);
> > +	    for (j = 0; j < (1U << log_sector_size);
> >  		 j += dev->cipher->cipher->blocksize)
> >  	      {
> >  		grub_crypto_xor (data + i + j, data + i + j, iv,
> > @@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (do_encrypt)
> >  	      err = grub_crypto_ecb_encrypt (dev->cipher, data +
> > i, data + i,
> > -					     (1U <<
> > dev->log_sector_size));
> > +					     (1U <<
> > log_sector_size)); else
> >  	      err = grub_crypto_ecb_decrypt (dev->cipher, data +
> > i, data + i,
> > -					     (1U <<
> > dev->log_sector_size));
> > +					     (1U <<
> > log_sector_size)); if (err)
> >  	      return err;
> >  	    lrw_xor (&sec, dev, data + i);
> > @@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_ECB:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size));
> > +					   (1U <<
> > log_sector_size)); else
> >  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size));
> > +					   (1U <<
> > log_sector_size)); if (err)
> >  	    return err;
> >  	  break;
> > @@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, gcry_err_code_t
> >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> >  			 grub_uint8_t * data, grub_size_t len,
> > -			 grub_disk_addr_t sector)
> > +			 grub_disk_addr_t sector, grub_size_t
> > log_sector_size) {
> > -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> > +  return grub_cryptodisk_endecrypt (dev, data, len, sector,
> > log_sector_size, 0); }
> >  
> >  grub_err_t
> > @@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk,
> > grub_disk_addr_t sector, }
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
> >  					size <<
> > disk->log_sector_size,
> > -					sector, 0);
> > +					sector,
> > dev->log_sector_size, 0); return grub_crypto_gcry_error (gcry_err);
> >  }
> >  
> > @@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk,
> > grub_disk_addr_t sector, 
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
> >  					size <<
> > disk->log_sector_size,
> > -					sector, 1);
> > +					sector,
> > disk->log_sector_size, 1); if (gcry_err)
> >      {
> >        grub_free (tmp);
> > diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> > index 59702067a..20cc20b9b 100644
> > --- a/grub-core/disk/luks.c
> > +++ b/grub-core/disk/luks.c
> > @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char
> > *check_uuid, return NULL;
> >    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> >    newdev->source_disk = NULL;
> > -  newdev->log_sector_size = 9;
> > +  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> >    newdev->total_length = grub_disk_get_size (disk) -
> > newdev->offset; grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
> >    newdev->modname = "luks";
> > @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
> >  	  return err;
> >  	}
> >  
> > -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > 0);
> > +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > 0,
> > +					  LUKS1_LOG_SECTOR_SIZE);
> >        if (gcry_err)
> >  	{
> >  	  grub_free (split_key);
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 9f7d6e12b..b7d3b425a 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -499,7 +499,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> >        goto err;
> >      }
> >  
> > -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > k->area.size, 0);
> > +  /*
> > +   * The key slots area is always encrypted in 512-byte sectors,
> > +   * regardless of encrypted data sector size.
> > +   */
> > +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > k->area.size, 0,
> > +				      LUKS1_LOG_SECTOR_SIZE);
> >    if (gcry_ret)
> >      {
> >        ret = grub_crypto_gcry_error (gcry_ret);
> > diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> > index e1b21e785..006f3ec49 100644
> > --- a/include/grub/cryptodisk.h
> > +++ b/include/grub/cryptodisk.h
> > @@ -48,6 +48,12 @@ typedef enum
> >  
> >  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
> >  
> > +/* LUKS1 specification defines the block size to always be 512
> > bytes. */ +#define LUKS1_LOG_SECTOR_SIZE 9
> > +
> > +/* By default dm-crypt increments the IV every 512 bytes. */
> > +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> > +
> >  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
> >  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
> >  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE
> > - 3) @@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t
> > dev, gcry_err_code_t
> >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> >  			 grub_uint8_t * data, grub_size_t len,
> > -			 grub_disk_addr_t sector);
> > +			 grub_disk_addr_t sector, grub_size_t
> > log_sector_size); grub_err_t
> >  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
> >  			grub_disk_t source);
> > -- 
> > 2.27.0
> > 


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

* Re: [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-09  9:44     ` Patrick Steinhardt
@ 2020-10-18 19:05       ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-18 19:05 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Fri, 9 Oct 2020 11:44:15 +0200
Patrick Steinhardt <ps@pks.im> wrote:

> On Sat, Oct 03, 2020 at 05:55:27PM -0500, Glenn Washburn wrote:
> > Use the keyslot key value in the keyslot json array rather than the
> > index of the keyslot in the json array. This is less confusing for
> > the end user. For example, say you have a LUKS2 device with a key
> > in slot 1 and slot 4. When using the password for slot 4 to unlock
> > the device, the messages using the index of the keyslot will
> > mention keyslot 1 (its a zero-based index). Furthermore,with this
> > change the keyslot number will align with the number used to
> > reference the keyslot when using the --key-slot argument to
> > cryptsetup.
> 
> The rationale does make sense to me, but I'm not sure I like cramming
> this information into another out-parameter. The result feels a bit
> hard to read to me and is not immediately obvious. How about we
> instead add another member "index" or similar to `struct
> grub_luks2_keyslot`?
> 
> Patrick

That's a great idea. I'll add it in the next version of the patch.

> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 27 ++++++++++++++-------------
> >  1 file changed, 14 insertions(+), 13 deletions(-)
> > 
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index c3cd63606..db251cce0 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -255,16 +255,16 @@ luks2_parse_digest (grub_luks2_digest_t *out,
> > const grub_json_t *digest) 
> >  static grub_err_t
> >  luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t
> > *d, grub_luks2_segment_t *s,
> > -		   const grub_json_t *root, grub_size_t
> > keyslot_idx)
> > +		   grub_uint64_t *keyslot_key, const grub_json_t
> > *root, grub_size_t keyslot_idx) {
> >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > segment; grub_size_t i, size;
> > -  grub_uint64_t keyslot_key, digest_key, segment_key;
> > +  grub_uint64_t digest_key, segment_key;
> >  
> >    /* Get nth keyslot */
> >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> > +      grub_json_getuint64 (keyslot_key, &keyslot, NULL) ||
> >        grub_json_getchild (&keyslot, &keyslot, 0) ||
> >        luks2_parse_keyslot (k, &keyslot))
> >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > keyslot index %"PRIuGRUB_SIZE, keyslot_idx); @@ -281,11 +281,11 @@
> > luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d,
> > grub_luks2_s luks2_parse_digest (d, &digest)) return grub_error
> > (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index
> > %"PRIuGRUB_SIZE, i); 
> > -      if ((d->keyslots & (1 << keyslot_key)))
> > +      if ((d->keyslots & (1 << *keyslot_key)))
> >  	break;
> >      }
> >    if (i == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", *keyslot_key); 
> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> > @@ -593,17 +593,18 @@ luks2_recover_key (grub_disk_t disk,
> >    /* Try all keyslot */
> >    for (i = 0; i < size; i++)
> >      {
> > -      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > i);
> > +      grub_uint64_t keyslot_key;
> > +      ret = luks2_get_keyslot (&keyslot, &digest, &segment,
> > &keyslot_key, json, i); if (ret)
> >  	goto err;
> >  
> >        if (keyslot.priority == 0)
> >  	{
> > -	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_SIZE" due to priority\n", i);
> > +	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key); continue;
> >          }
> >  
> > -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n",
> > i);
> > +      grub_dprintf ("luks2", "Trying keyslot
> > %"PRIuGRUB_UINT64_T"\n", keyslot_key); 
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); @@ -618,16 +619,16 @@ luks2_recover_key
> > (grub_disk_t disk, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_SIZE" failed: %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_UINT64_T" failed: %s\n",
> > +			keyslot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> >        ret = luks2_verify_key (&digest, candidate_key,
> > keyslot.key_size); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_SIZE": %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_UINT64_T": %s\n",
> > +			keyslot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> > @@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
> >         * TRANSLATORS: It's a cryptographic key slot: one element
> > of an array
> >         * where each element is either empty or holds a key.
> >         */
> > -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> > +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"),
> > keyslot_key); 
> >        candidate_key_len = keyslot.key_size;
> >        break;
> > -- 
> > 2.27.0
> > 


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

* Re: [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-18 18:23     ` Glenn Washburn
@ 2020-10-19 11:27       ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-19 11:27 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

Hi Glenn,

I will be looking at the patches on the grub-devel this week. I will
send you my comments then.

Daniel

On Sun, Oct 18, 2020 at 01:23:25PM -0500, Glenn Washburn wrote:
> Daniel, Patrick,
>
> Have either of you had a chance to review this patch?  Daniel, this is
> my interpretation of what you suggested earlier to remove constant
> literals in this message:
> https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00069.html
>
> I'm going to make a v3 patchset with Patrick's suggested changes.
> Please reply to that patch.
>
> Glenn
>
> On Sat,  3 Oct 2020 17:55:31 -0500
> Glenn Washburn <development@efficientek.com> wrote:
>
> > This should improve readability of code by providing clues as to what
> > the value represents.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 12 +++++++-----
> >  include/grub/types.h        |  3 +++
> >  2 files changed, 10 insertions(+), 5 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> > index 623f0f396..1a91c2d55 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > log_sector_size));
> > +	  /* The IV is the 64 bit byte offset of the sector. */
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
> > +					       - log_sector_size));
> >  	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> > -				    & 0xFFFFFFFF);
> > +				    & GRUB_TYPE_MAX(iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >  	  {
> >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> > -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > +	    iv[sz - 2] = grub_cpu_to_be32 (num >>
> > GRUB_TYPE_BIT(iv[0]));
> > +	    iv[sz - 1] = grub_cpu_to_be32 (num &
> > GRUB_TYPE_MAX(iv[0])); }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
> >  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >  					 dev->cipher->cipher->blocksize);
> >  	  if (err)
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index 035a4b528..8b4267ebd 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void
> > *ptr, grub_uint64_t val)
> >  #define GRUB_CHAR_BIT 8
> >
> > +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
> > +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) -
> > 1)) - 1)) + 1) +
> >  #endif /* ! GRUB_TYPES_HEADER */


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

* Re: [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-09 10:00     ` Patrick Steinhardt
@ 2020-10-19 16:27       ` Glenn Washburn
  2020-10-23 17:46         ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 16:27 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Fri, 9 Oct 2020 12:00:47 +0200
Patrick Steinhardt <ps@pks.im> wrote:

> On Sat, Oct 03, 2020 at 05:55:34PM -0500, Glenn Washburn wrote:
> > This makes it more obvious to the reader that the disk referred to
> > is the source disk, as opposed to say the disk holding the
> > cryptodisk.
> 
> Hum. I'm not sure this actually helps readability, mostly because I
> think that the distinction here is not that helpful in the context of
> encryption or decryption of the device. In the end we are trying to
> encrypt or decrypt the disk in order to create the new cryptodisk.
> 
> Anyway, I don't particularly care, so take this just as my two cents.
> The patch itself looks good to me.
> 
> Patrick

If I'm following you, you're saying that because encryption is
reversible, `source` is not helpful because either plaintext or
encrypted data can be the source depending on if you're encrypting or
decrypting.

In our case here, I think its intuitive to call the disk `source`
because it is where the data is coming from and to distinguish it from
the cryptodisk grub_disk_t. So its not called source because of the
(encrypted) contents of the disk, as I think you're suggesting. I think
this patch makes more sense in the context of some cryptodisk.c and
luks.c code.

Note that in grub_cryptodisk_scan_device_real in cryptodisk.c
which calls luks2_recover_key the grub_disk_t passed is named `source`.
And in in grub_cryptodisk_open, the parameter `disk` refers to a
grub_disk_t that can be read to decrypt an associated encrypted
grub_disk_t (ie. the cryptodisk grub_disk_t). The grub_cryptodisk_t
associated in disk->data has a member named "source_disk" which points
to the associated grub_disk_t and member "source" which is the name of
the associated disk. In both luks2_decrypt_key and luks2_recover_key the
grub_disk_t argument refers to the encrypted grub_disk_t which can be
accessed as (unencrypted disk)->data->source_disk on the opened crypto
disk. So I think its consistent with cryptodisk.c naming conventions to
call the grub_disk_t argument "source". Also as the subject line says,
this creates consistency with luks.c in its luks2_decrypt_key, which I
suspect is named "source" for the reasons I outlined above. 

I'm a little confused by "In the end we are trying to encrypt or
decrypt the disk in order to create the new cryptodisk." Where does
"encrypt" fit in to creating the new cryptodisk?

> 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 22 +++++++++++-----------
> >  1 file changed, 11 insertions(+), 11 deletions(-)
> > 
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 46abc96ef..f918f5a52 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -416,7 +416,7 @@ luks2_verify_key (grub_luks2_digest_t *d,
> > grub_uint8_t *candidate_key, 
> >  static grub_err_t
> >  luks2_decrypt_key (grub_uint8_t *out_key,
> > -		   grub_disk_t disk, grub_cryptodisk_t crypt,
> > +		   grub_disk_t source, grub_cryptodisk_t crypt,
> >  		   grub_luks2_keyslot_t *k,
> >  		   const grub_uint8_t *passphrase, grub_size_t
> > passphraselen) {
> > @@ -492,7 +492,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> >      }
> >  
> >    grub_errno = GRUB_ERR_NONE;
> > -  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size,
> > split_key);
> > +  ret = grub_disk_read (source, 0, k->area.offset, k->area.size,
> > split_key); if (ret)
> >      {
> >        grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
> > @@ -536,7 +536,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> >  }
> >  
> >  static grub_err_t
> > -luks2_recover_key (grub_disk_t disk,
> > +luks2_recover_key (grub_disk_t source,
> >  		   grub_cryptodisk_t crypt)
> >  {
> >    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
> > @@ -551,7 +551,7 @@ luks2_recover_key (grub_disk_t disk,
> >    grub_json_t *json = NULL, keyslots;
> >    grub_err_t ret;
> >  
> > -  ret = luks2_read_header (disk, &header);
> > +  ret = luks2_read_header (source, &header);
> >    if (ret)
> >      return ret;
> >  
> > @@ -560,7 +560,7 @@ luks2_recover_key (grub_disk_t disk,
> >        return GRUB_ERR_OUT_OF_MEMORY;
> >  
> >    /* Read the JSON area. */
> > -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64
> > (header.hdr_offset) + sizeof (header),
> > +  ret = grub_disk_read (source, 0, grub_be_to_cpu64
> > (header.hdr_offset) + sizeof (header), grub_be_to_cpu64
> > (header.hdr_size) - sizeof (header), json_header); if (ret)
> >        goto err;
> > @@ -577,10 +577,10 @@ luks2_recover_key (grub_disk_t disk,
> >      }
> >  
> >    /* Get the passphrase from the user. */
> > -  if (disk->partition)
> > -    part = grub_partition_get_name (disk->partition);
> > -  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "),
> > disk->name,
> > -		disk->partition ? "," : "", part ? : "",
> > +  if (source->partition)
> > +    part = grub_partition_get_name (source->partition);
> > +  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "),
> > source->name,
> > +		source->partition ? "," : "", part ? : "",
> >  		crypt->uuid);
> >    if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> >      {
> > @@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
> >        crypt->log_sector_size = sizeof (unsigned int) * 8
> >  		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1; if (grub_strcmp (segment.size, "dynamic")
> > == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (disk) >>
> > (crypt->log_sector_size - disk->log_sector_size))
> > +	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> >  			       - crypt->offset_sectors;
> >        else
> >  	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size; 
> > -      ret = luks2_decrypt_key (candidate_key, disk, crypt,
> > &keyslot,
> > +      ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> > -- 
> > 2.27.0
> > 


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

* [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux
  2020-10-09 10:01   ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
@ 2020-10-19 23:09     ` Glenn Washburn
  2020-10-19 23:09       ` [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
                         ` (11 more replies)
  0 siblings, 12 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Heres an updated patch series which addresses comment from Patrick. The only
code change is adding a slot_key member to grub_luks2_keyslot and using that
instead of an extra out parameter to luks2_get_keyslot.

Glenn Washburn (10):
  luks2: Fix use of incorrect index and some grub_error() messages.
  luks2: Improve readability in luks2_get_keyslot.
  luks2: Use more intuitive keyslot key instead of index when naming
    keyslot.
  luks2: grub_cryptodisk_t->total_length is the max number of device
    native sectors
  cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  cryptodisk: Properly handle non-512 byte sized sectors.
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt.
  cryptodisk: Rename total_length field in grub_cryptodisk_t to
    total_sectors.
  cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  luks2: Rename source disk variabled named 'disk' to 'source' as in
    luks.c.

 grub-core/disk/cryptodisk.c | 78 +++++++++++++++++++--------------
 grub-core/disk/geli.c       |  4 +-
 grub-core/disk/luks.c       |  9 ++--
 grub-core/disk/luks2.c      | 86 ++++++++++++++++++++-----------------
 include/grub/cryptodisk.h   | 18 ++++++--
 include/grub/types.h        |  3 ++
 6 files changed, 117 insertions(+), 81 deletions(-)

Range-diff against v2:
1:  e2433b8ab ! 1:  1f65a04e0 luks2: Use more intuitive keyslot key instead of index when naming keyslot.
    @@ Commit message
         cryptsetup.
     
      ## grub-core/disk/luks2.c ##
    -@@ grub-core/disk/luks2.c: luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
    +@@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
      
    - static grub_err_t
    - luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
    --		   const grub_json_t *root, grub_size_t keyslot_idx)
    -+		   grub_uint64_t *keyslot_key, const grub_json_t *root, grub_size_t keyslot_idx)
    + struct grub_luks2_keyslot
    + {
    ++  grub_uint64_t slot_key;
    +   grub_int64_t key_size;
    +   grub_int64_t priority;
    +   struct
    +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
      {
        grub_json_t keyslots, keyslot, digests, digest, segments, segment;
        grub_size_t i, size;
    @@ grub-core/disk/luks2.c: luks2_parse_digest (grub_luks2_digest_t *out, const grub
        if (grub_json_getvalue (&keyslots, root, "keyslots") ||
            grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
     -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
    -+      grub_json_getuint64 (keyslot_key, &keyslot, NULL) ||
    ++      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
            grub_json_getchild (&keyslot, &keyslot, 0) ||
            luks2_parse_keyslot (k, &keyslot))
          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
      
     -      if ((d->keyslots & (1 << keyslot_key)))
    -+      if ((d->keyslots & (1 << *keyslot_key)))
    ++      if ((d->keyslots & (1 << k->slot_key)))
      	break;
          }
        if (i == size)
     -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
    -+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", *keyslot_key);
    ++      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
      
        /* Get segment that matches the digest. */
        if (grub_json_getvalue (&segments, root, "segments") ||
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    -   /* Try all keyslot */
    -   for (i = 0; i < size; i++)
    -     {
    --      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
    -+      grub_uint64_t keyslot_key;
    -+      ret = luks2_get_keyslot (&keyslot, &digest, &segment, &keyslot_key, json, i);
    -       if (ret)
    - 	goto err;
      
            if (keyslot.priority == 0)
      	{
     -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
    -+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot_key);
    ++	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
      	  continue;
              }
      
     -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
    -+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
    ++      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
      
            /* Set up disk according to keyslot's segment. */
            crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
     -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
     -			i, grub_errmsg);
     +	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
    -+			keyslot_key, grub_errmsg);
    ++			keyslot.slot_key, grub_errmsg);
      	  continue;
      	}
      
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
     -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
     -			i, grub_errmsg);
     +	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
    -+			keyslot_key, grub_errmsg);
    ++			keyslot.slot_key, grub_errmsg);
      	  continue;
      	}
      
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
             * where each element is either empty or holds a key.
             */
     -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
    -+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot_key);
    ++      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
      
            candidate_key_len = keyslot.key_size;
            break;
2:  3baffdd4f ! 2:  fcb72f70d luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
    @@ Commit message
         The total_length field is named confusingly because length usually refers to
         bytes, whereas in this case its really the total number of sectors on the
         device. Also counter-intuitively, grub_disk_get_size returns the total
    -    number of device native sectors sectors. We need to convert the sectors from
    -    the size of the underlying device to the cryptodisk sector size. And
    +    number of device native sectors. We need to convert the sectors from the
    +    size of the underlying device to the cryptodisk sector size. And
         segment.size is in bytes which need to be converted to cryptodisk sectors.
     
         Also, removed an empty statement.
3:  6da3d8598 = 3:  e8e069cae cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
4:  fd7cb6b16 = 4:  6fe26ba56 cryptodisk: Properly handle non-512 byte sized sectors.
5:  b33733199 = 5:  3918a9013 cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
6:  de4f6b2e5 ! 6:  28e0cac66 cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
    @@ Metadata
      ## Commit message ##
         cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
     
    -    This makes the creates an alignment with grub_disk_t naming of the same
    -    field and is more intuitive as to how it should be used.
    +    This creates an alignment with grub_disk_t naming of the same field and is
    +    more intuitive as to how it should be used.
     
      ## grub-core/disk/cryptodisk.c ##
     @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_open (const char *name, grub_disk_t disk)
7:  a165791de ! 7:  74c6232c9 cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
    @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot_key);
    +       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
      
            /* Set up disk according to keyslot's segment. */
     -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
8:  86beb5be8 = 8:  738fe0139 luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
-- 
2.27.0



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

* [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 12:08         ` Daniel Kiper
  2020-10-19 23:09       ` [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
                         ` (10 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

When looping over the digests and segments, the loop variable is j, but the
variable i is used to index in the the digests and segments json array. The
variable i is the keyslot index. Similarly, there are several grub_error()
statements using the wrong index in constructing the error string.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 31d7166fc..2241e0312 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
   for (j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&digest, &digests, i) ||
+      if (grub_json_getchild (&digest, &digests, j) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
 
       if ((d->keyslots & (1 << idx)))
 	break;
     }
   if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (j = 0; j < size; j++)
+  for (i = j, j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&segment, &segments, i) ||
+      if (grub_json_getchild (&segment, &segments, j) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
 
       if ((d->segments & (1 << idx)))
 	break;
     }
   if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
  2020-10-19 23:09       ` [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 12:14         ` Daniel Kiper
  2020-10-19 23:09       ` [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
                         ` (9 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Introduce new variables keyslot_key, digest_key, and segment_key which
represent the integer key of the item in the respective associative array
when looping over the array items. This replaces using a generically
named variable named "idx" used for all three values. The parameter "i"
is renamed to "keyslot_idx" and the loop variable "j" is renamed to "i".
Error messages now distinguish between indexes and keys.  The former
include "index" in the error string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2241e0312..c3cd63606 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,54 +255,55 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t i)
+		   const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
-  grub_size_t j, size;
-  grub_uint64_t idx;
+  grub_size_t i, size;
+  grub_uint64_t keyslot_key, digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
-      grub_json_getchild (&keyslot, &keyslots, i) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
+      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, i);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
       grub_json_getsize (&size, &digests))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
-  for (j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&digest, &digests, j) ||
+      if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << keyslot_key)))
 	break;
     }
-  if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
+  if (i == size)
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (i = j, j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&segment, &segments, j) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+      if (grub_json_getchild (&segment, &segments, i) ||
+	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << segment_key)))
 	break;
     }
-  if (j == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
+  if (i == size)
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", digest_key);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
  2020-10-19 23:09       ` [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
  2020-10-19 23:09       ` [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 17:55         ` Patrick Steinhardt
  2020-10-19 23:09       ` [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
                         ` (8 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the keyslot key value in the keyslot json array rather than the index of
the keyslot in the json array. This is less confusing for the end user. For
example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
using the password for slot 4 to unlock the device, the messages using the
index of the keyslot will mention keyslot 1 (its a zero-based index).
Furthermore,with this change the keyslot number will align with the number
used to reference the keyslot when using the --key-slot argument to
cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c3cd63606..4e1e47161 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  grub_uint64_t slot_key;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -259,12 +260,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t keyslot_key, digest_key, segment_key;
+  grub_uint64_t digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
@@ -281,11 +282,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << keyslot_key)))
+      if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -599,11 +600,11 @@ luks2_recover_key (grub_disk_t disk,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -618,16 +619,16 @@ luks2_recover_key (grub_disk_t disk,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (2 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 18:03         ` Patrick Steinhardt
  2020-10-19 23:09       ` [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
                         ` (7 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

The total_length field is named confusingly because length usually refers to
bytes, whereas in this case its really the total number of sectors on the
device. Also counter-intuitively, grub_disk_get_size returns the total
number of device native sectors. We need to convert the sectors from the
size of the underlying device to the cryptodisk sector size. And
segment.size is in bytes which need to be converted to cryptodisk sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 4e1e47161..311d18684 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -425,7 +425,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -611,9 +611,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
+	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (3 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 12:21         ` Daniel Kiper
  2020-10-19 23:09       ` [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                         ` (6 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

When setting cipher IV mode, detection is done by prefix matching the
cipher IV mode part of the cipher mode string.  Since "plain" matches
"plain64", we must check for "plain64" first.  Otherwise, "plain64" will
be detected as "plain".

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/cryptodisk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 13af84dd1..a3d672f68 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -501,10 +501,10 @@ grub_cryptodisk_setcipher (grub_cryptodisk_t crypt, const char *ciphername, cons
 
   if (cipheriv == NULL)
       ;
-  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
-      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
       mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
+  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
+      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
   else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
     {
       if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
-- 
2.27.0



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

* [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (4 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 18:09         ` Patrick Steinhardt
  2020-10-30 20:47         ` Daniel Kiper
  2020-10-19 23:09       ` [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                         ` (5 subsequent siblings)
  11 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 47 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index a3d672f68..623f0f396 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
+	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 59702067a..20cc20b9b 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
   newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 311d18684..b9e0e98e1 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -500,7 +500,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index e1b21e785..006f3ec49 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (5 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 18:01         ` Patrick Steinhardt
  2020-10-27 18:03         ` Daniel Kiper
  2020-10-19 23:09       ` [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
                         ` (4 subsequent siblings)
  11 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 12 +++++++-----
 include/grub/types.h        |  3 +++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 623f0f396..1a91c2d55 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
+	  /* The IV is the 64 bit byte offset of the sector. */
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
+					       - log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_MAX(iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528..8b4267ebd 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
 
 #define GRUB_CHAR_BIT 8
 
+#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
+#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)
+
 #endif /* ! GRUB_TYPES_HEADER */
-- 
2.27.0



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

* [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (6 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 17:58         ` Patrick Steinhardt
  2020-10-19 23:09       ` [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
                         ` (3 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This creates an alignment with grub_disk_t naming of the same field and is
more intuitive as to how it should be used.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 2 +-
 grub-core/disk/geli.c       | 2 +-
 grub-core/disk/luks.c       | 2 +-
 grub-core/disk/luks2.c      | 4 ++--
 include/grub/cryptodisk.h   | 3 ++-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 1a91c2d55..f5d098f65 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -711,7 +711,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
     }
 
   disk->data = dev;
-  disk->total_sectors = dev->total_length;
+  disk->total_sectors = dev->total_sectors;
   disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
   disk->id = dev->id;
   dev->ref++;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d23299a..4ec875821 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_length = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = 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;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 20cc20b9b..545734342 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index b9e0e98e1..bae54936c 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -616,10 +616,10 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
 			       - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 006f3ec49..9e10ae927 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -73,7 +73,8 @@ struct grub_cryptodisk
 
   char *source;
   grub_disk_addr_t offset;
-  grub_disk_addr_t total_length;
+  /* Total number of encrypted sectors of size (1<<log_sector_size) */
+  grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
   int ref;
   grub_crypto_cipher_handle_t cipher;
-- 
2.27.0



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

* [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (7 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 17:58         ` Patrick Steinhardt
  2020-10-19 23:09       ` [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
                         ` (2 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This makes it clear that the offset represents sectors, not bytes, in order
to improve readability.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 10 +++++-----
 grub-core/disk/geli.c       |  2 +-
 grub-core/disk/luks.c       |  4 ++--
 grub-core/disk/luks2.c      |  4 ++--
 include/grub/cryptodisk.h   |  7 ++++++-
 5 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index f5d098f65..64a51165c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -766,10 +766,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   err = grub_disk_read (dev->source_disk,
-			grub_disk_from_native_sector (disk, sector + dev->offset),
+			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
 			0, size << disk->log_sector_size, buf);
   if (err)
     {
@@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
@@ -827,7 +827,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
     }
 
   /* Since ->write was called so disk.mod is loaded but be paranoid  */
-  sector = sector + dev->offset;
+  sector = sector + dev->offset_sectors;
   if (grub_disk_write_weak)
     err = grub_disk_write_weak (dev->source_disk,
 				grub_disk_from_native_sector (disk, sector),
@@ -1240,7 +1240,7 @@ luks_script_get (grub_size_t *sz)
 	ptr = grub_stpcpy (ptr, "luks_mount ");
 	ptr = grub_stpcpy (ptr, i->uuid);
 	*ptr++ = ' ';
-	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
+	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
 	while (*ptr)
 	  ptr++;
 	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 4ec875821..0175ce4c4 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     }
   newdev->cipher = cipher;
   newdev->secondary_cipher = secondary_cipher;
-  newdev->offset = 0;
+  newdev->offset_sectors = 0;
   newdev->source_disk = NULL;
   newdev->benbi_log = 0;
   if (grub_le_to_cpu16 (header.alg) == 0x16)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 545734342..88f2da493 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
       return NULL;
-  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
+  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index bae54936c..cd573208a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -612,12 +612,12 @@ luks2_recover_key (grub_disk_t disk,
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
-      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
+      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
 	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
-			       - crypt->offset;
+			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 9e10ae927..c8eef2204 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -72,7 +72,12 @@ struct grub_cryptodisk
   struct grub_cryptodisk **prev;
 
   char *source;
-  grub_disk_addr_t offset;
+
+  /*
+   * The number of sectors the start of the encrypted data is offset into the
+   * underlying disk, where sectors are the size noted by log_sector_size.
+   */
+  grub_disk_addr_t offset_sectors;
   /* Total number of encrypted sectors of size (1<<log_sector_size) */
   grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
-- 
2.27.0



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

* [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (8 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-10-19 23:09       ` Glenn Washburn
  2020-10-23 18:01         ` Patrick Steinhardt
  2020-10-27 19:25       ` [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux Daniel Kiper
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-19 23:09 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This makes it more obvious to the reader that the disk referred to is the
source disk, as opposed to say the disk holding the cryptodisk.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index cd573208a..ccb94e80d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -417,7 +417,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
 
 static grub_err_t
 luks2_decrypt_key (grub_uint8_t *out_key,
-		   grub_disk_t disk, grub_cryptodisk_t crypt,
+		   grub_disk_t source, grub_cryptodisk_t crypt,
 		   grub_luks2_keyslot_t *k,
 		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
 {
@@ -493,7 +493,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
     }
 
   grub_errno = GRUB_ERR_NONE;
-  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
+  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
   if (ret)
     {
       grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
@@ -537,7 +537,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 }
 
 static grub_err_t
-luks2_recover_key (grub_disk_t disk,
+luks2_recover_key (grub_disk_t source,
 		   grub_cryptodisk_t crypt)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
@@ -552,7 +552,7 @@ luks2_recover_key (grub_disk_t disk,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  ret = luks2_read_header (disk, &header);
+  ret = luks2_read_header (source, &header);
   if (ret)
     return ret;
 
@@ -561,7 +561,7 @@ luks2_recover_key (grub_disk_t disk,
       return GRUB_ERR_OUT_OF_MEMORY;
 
   /* Read the JSON area. */
-  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
+  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
 			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
   if (ret)
       goto err;
@@ -578,10 +578,10 @@ luks2_recover_key (grub_disk_t disk,
     }
 
   /* Get the passphrase from the user. */
-  if (disk->partition)
-    part = grub_partition_get_name (disk->partition);
-  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
-		disk->partition ? "," : "", part ? : "",
+  if (source->partition)
+    part = grub_partition_get_name (source->partition);
+  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+		source->partition ? "," : "", part ? : "",
 		crypt->uuid);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     {
@@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
 			       - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
-      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
+      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-- 
2.27.0



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

* Re: [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-19 23:09       ` [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
@ 2020-10-23 12:08         ` Daniel Kiper
  2020-10-23 17:52           ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-10-23 12:08 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:49PM -0500, Glenn Washburn wrote:
> When looping over the digests and segments, the loop variable is j, but the
> variable i is used to index in the the digests and segments json array. The
> variable i is the keyslot index. Similarly, there are several grub_error()
> statements using the wrong index in constructing the error string.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 31d7166fc..2241e0312 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
>    for (j = 0; j < size; j++)
>      {
> -      if (grub_json_getchild (&digest, &digests, i) ||
> +      if (grub_json_getchild (&digest, &digests, j) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
>
>        if ((d->keyslots & (1 << idx)))
>  	break;
>      }
>    if (j == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
>
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
>        grub_json_getsize (&size, &segments))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
> -  for (j = 0; j < size; j++)
> +  for (i = j, j = 0; j < size; j++)

Should not it be "i = j = 0" instead of "i = j, j = 0"?

>      {
> -      if (grub_json_getchild (&segment, &segments, i) ||
> +      if (grub_json_getchild (&segment, &segments, j) ||
>  	  grub_json_getuint64 (&idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
>
>        if ((d->segments & (1 << idx)))
>  	break;
>      }
>    if (j == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);

s/PRIuGRUB_SIZE, i/PRIuGRUB_SIZE, j/?

Daniel


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

* Re: [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-19 23:09       ` [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
@ 2020-10-23 12:14         ` Daniel Kiper
  2020-10-29 21:52           ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-10-23 12:14 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:50PM -0500, Glenn Washburn wrote:
> Introduce new variables keyslot_key, digest_key, and segment_key which
> represent the integer key of the item in the respective associative array
> when looping over the array items. This replaces using a generically
> named variable named "idx" used for all three values. The parameter "i"
> is renamed to "keyslot_idx" and the loop variable "j" is renamed to "i".
> Error messages now distinguish between indexes and keys.  The former
> include "index" in the error string, and the later are surrounded in quotes.

I think this patch does too many things in one step. Please do one
rename per patch if possible. Additionally, I think this patch, or
series of the patches, should be before current patch #1.

Daniel


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

* Re: [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
  2020-10-19 23:09       ` [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
@ 2020-10-23 12:21         ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-23 12:21 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:53PM -0500, Glenn Washburn wrote:
> When setting cipher IV mode, detection is done by prefix matching the
> cipher IV mode part of the cipher mode string.  Since "plain" matches
> "plain64", we must check for "plain64" first.  Otherwise, "plain64" will
> be detected as "plain".
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-19 16:27       ` Glenn Washburn
@ 2020-10-23 17:46         ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 17:46 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 11:27:12AM -0500, Glenn Washburn wrote:
> On Fri, 9 Oct 2020 12:00:47 +0200
> Patrick Steinhardt <ps@pks.im> wrote:
> 
> > On Sat, Oct 03, 2020 at 05:55:34PM -0500, Glenn Washburn wrote:
> > > This makes it more obvious to the reader that the disk referred to
> > > is the source disk, as opposed to say the disk holding the
> > > cryptodisk.
> > 
> > Hum. I'm not sure this actually helps readability, mostly because I
> > think that the distinction here is not that helpful in the context of
> > encryption or decryption of the device. In the end we are trying to
> > encrypt or decrypt the disk in order to create the new cryptodisk.
> > 
> > Anyway, I don't particularly care, so take this just as my two cents.
> > The patch itself looks good to me.
> > 
> > Patrick
> 
> If I'm following you, you're saying that because encryption is
> reversible, `source` is not helpful because either plaintext or
> encrypted data can be the source depending on if you're encrypting or
> decrypting.

> In our case here, I think its intuitive to call the disk `source`
> because it is where the data is coming from and to distinguish it from
> the cryptodisk grub_disk_t. So its not called source because of the
> (encrypted) contents of the disk, as I think you're suggesting. I think
> this patch makes more sense in the context of some cryptodisk.c and
> luks.c code.
> 
> Note that in grub_cryptodisk_scan_device_real in cryptodisk.c
> which calls luks2_recover_key the grub_disk_t passed is named `source`.
> And in in grub_cryptodisk_open, the parameter `disk` refers to a
> grub_disk_t that can be read to decrypt an associated encrypted
> grub_disk_t (ie. the cryptodisk grub_disk_t). The grub_cryptodisk_t
> associated in disk->data has a member named "source_disk" which points
> to the associated grub_disk_t and member "source" which is the name of
> the associated disk. In both luks2_decrypt_key and luks2_recover_key the
> grub_disk_t argument refers to the encrypted grub_disk_t which can be
> accessed as (unencrypted disk)->data->source_disk on the opened crypto
> disk. So I think its consistent with cryptodisk.c naming conventions to
> call the grub_disk_t argument "source". Also as the subject line says,
> this creates consistency with luks.c in its luks2_decrypt_key, which I
> suspect is named "source" for the reasons I outlined above. 
> 
> I'm a little confused by "In the end we are trying to encrypt or
> decrypt the disk in order to create the new cryptodisk." Where does
> "encrypt" fit in to creating the new cryptodisk?

Let's just keep your patch if others think it helps readability. As I
said, I don't particularly care as to me the old naming was already
quite clear.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages.
  2020-10-23 12:08         ` Daniel Kiper
@ 2020-10-23 17:52           ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 17:52 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Glenn Washburn

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

On Fri, Oct 23, 2020 at 02:08:18PM +0200, Daniel Kiper wrote:
> On Mon, Oct 19, 2020 at 06:09:49PM -0500, Glenn Washburn wrote:
> > When looping over the digests and segments, the loop variable is j, but the
> > variable i is used to index in the the digests and segments json array. The
> > variable i is the keyslot index. Similarly, there are several grub_error()
> > statements using the wrong index in constructing the error string.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 31d7166fc..2241e0312 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -275,34 +275,34 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
> >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
> >    for (j = 0; j < size; j++)
> >      {
> > -      if (grub_json_getchild (&digest, &digests, i) ||
> > +      if (grub_json_getchild (&digest, &digests, j) ||
> >            grub_json_getchild (&digest, &digest, 0) ||
> >            luks2_parse_digest (d, &digest))
> > -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> > +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
> >
> >        if ((d->keyslots & (1 << idx)))
> >  	break;
> >      }
> >    if (j == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
> >
> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> >        grub_json_getsize (&size, &segments))
> >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
> > -  for (j = 0; j < size; j++)
> > +  for (i = j, j = 0; j < size; j++)
> 
> Should not it be "i = j = 0" instead of "i = j, j = 0"?

The intent is to save the digest index here...

> >      {
> > -      if (grub_json_getchild (&segment, &segments, i) ||
> > +      if (grub_json_getchild (&segment, &segments, j) ||
> >  	  grub_json_getuint64 (&idx, &segment, NULL) ||
> >  	  grub_json_getchild (&segment, &segment, 0) ||
> >            luks2_parse_segment (s, &segment))
> > -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> > +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
> >
> >        if ((d->segments & (1 << idx)))
> >  	break;
> >      }
> >    if (j == size)
> > -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> > +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
> 
> s/PRIuGRUB_SIZE, i/PRIuGRUB_SIZE, j/?
> 
> Daniel

... which then gets used here. It initially confused me as well, but it
should be correct. The problem is the awkward naming, but the patch
following this one improves the situation.

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-10-19 23:09       ` [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-10-23 17:55         ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 17:55 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:51PM -0500, Glenn Washburn wrote:
> Use the keyslot key value in the keyslot json array rather than the index of
> the keyslot in the json array. This is less confusing for the end user. For
> example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
> using the password for slot 4 to unlock the device, the messages using the
> index of the keyslot will mention keyslot 1 (its a zero-based index).
> Furthermore,with this change the keyslot number will align with the number
> used to reference the keyslot when using the --key-slot argument to
> cryptsetup.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

> ---
>  grub-core/disk/luks2.c | 23 ++++++++++++-----------
>  1 file changed, 12 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index c3cd63606..4e1e47161 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
>  
>  struct grub_luks2_keyslot
>  {
> +  grub_uint64_t slot_key;
>    grub_int64_t key_size;
>    grub_int64_t priority;
>    struct
> @@ -259,12 +260,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t keyslot_key, digest_key, segment_key;
> +  grub_uint64_t digest_key, segment_key;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -281,11 +282,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>            luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << keyslot_key)))
> +      if ((d->keyslots & (1 << k->slot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -599,11 +600,11 @@ luks2_recover_key (grub_disk_t disk,
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
>  	  continue;
>          }
>  
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -618,16 +619,16 @@ luks2_recover_key (grub_disk_t disk,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -635,7 +636,7 @@ luks2_recover_key (grub_disk_t disk,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> -- 
> 2.27.0

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-19 23:09       ` [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-10-23 17:58         ` Patrick Steinhardt
  2020-10-27 18:07           ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 17:58 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:57PM -0500, Glenn Washburn wrote:
> This makes it clear that the offset represents sectors, not bytes, in order
> to improve readability.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

> ---
>  grub-core/disk/cryptodisk.c | 10 +++++-----
>  grub-core/disk/geli.c       |  2 +-
>  grub-core/disk/luks.c       |  4 ++--
>  grub-core/disk/luks2.c      |  4 ++--
>  include/grub/cryptodisk.h   |  7 ++++++-
>  5 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index f5d098f65..64a51165c 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -766,10 +766,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    err = grub_disk_read (dev->source_disk,
> -			grub_disk_from_native_sector (disk, sector + dev->offset),
> +			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
>  			0, size << disk->log_sector_size, buf);
>    if (err)
>      {
> @@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> @@ -827,7 +827,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>  
>    /* Since ->write was called so disk.mod is loaded but be paranoid  */
> -  sector = sector + dev->offset;
> +  sector = sector + dev->offset_sectors;
>    if (grub_disk_write_weak)
>      err = grub_disk_write_weak (dev->source_disk,
>  				grub_disk_from_native_sector (disk, sector),
> @@ -1240,7 +1240,7 @@ luks_script_get (grub_size_t *sz)
>  	ptr = grub_stpcpy (ptr, "luks_mount ");
>  	ptr = grub_stpcpy (ptr, i->uuid);
>  	*ptr++ = ' ';
> -	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
> +	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
>  	while (*ptr)
>  	  ptr++;
>  	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index 4ec875821..0175ce4c4 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>      }
>    newdev->cipher = cipher;
>    newdev->secondary_cipher = secondary_cipher;
> -  newdev->offset = 0;
> +  newdev->offset_sectors = 0;
>    newdev->source_disk = NULL;
>    newdev->benbi_log = 0;
>    if (grub_le_to_cpu16 (header.alg) == 0x16)
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 545734342..88f2da493 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
>    if (!newdev)
>        return NULL;
> -  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> +  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> -  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index bae54936c..cd573208a 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -612,12 +612,12 @@ luks2_recover_key (grub_disk_t disk,
>        grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>  
>        /* Set up disk according to keyslot's segment. */
> -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> +      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
>  	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> -			       - crypt->offset;
> +			       - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 9e10ae927..c8eef2204 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -72,7 +72,12 @@ struct grub_cryptodisk
>    struct grub_cryptodisk **prev;
>  
>    char *source;
> -  grub_disk_addr_t offset;
> +
> +  /*
> +   * The number of sectors the start of the encrypted data is offset into the
> +   * underlying disk, where sectors are the size noted by log_sector_size.
> +   */
> +  grub_disk_addr_t offset_sectors;
>    /* Total number of encrypted sectors of size (1<<log_sector_size) */
>    grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-19 23:09       ` [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-10-23 17:58         ` Patrick Steinhardt
  2020-10-27 18:06           ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 17:58 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:56PM -0500, Glenn Washburn wrote:
> This creates an alignment with grub_disk_t naming of the same field and is
> more intuitive as to how it should be used.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

> ---
>  grub-core/disk/cryptodisk.c | 2 +-
>  grub-core/disk/geli.c       | 2 +-
>  grub-core/disk/luks.c       | 2 +-
>  grub-core/disk/luks2.c      | 4 ++--
>  include/grub/cryptodisk.h   | 3 ++-
>  5 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 1a91c2d55..f5d098f65 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -711,7 +711,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
>      }
>  
>    disk->data = dev;
> -  disk->total_sectors = dev->total_length;
> +  disk->total_sectors = dev->total_sectors;
>    disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
>    disk->id = dev->id;
>    dev->ref++;
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index e9d23299a..4ec875821 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>  
>    newdev->modname = "geli";
>  
> -  newdev->total_length = grub_disk_get_size (disk) - 1;
> +  newdev->total_sectors = 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;
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 20cc20b9b..545734342 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> -  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index b9e0e98e1..bae54936c 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -616,10 +616,10 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
>  			       - crypt->offset;
>        else
> -	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 006f3ec49..9e10ae927 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -73,7 +73,8 @@ struct grub_cryptodisk
>  
>    char *source;
>    grub_disk_addr_t offset;
> -  grub_disk_addr_t total_length;
> +  /* Total number of encrypted sectors of size (1<<log_sector_size) */
> +  grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
>    int ref;
>    grub_crypto_cipher_handle_t cipher;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-19 23:09       ` [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-10-23 18:01         ` Patrick Steinhardt
  2020-10-26 18:25           ` Glenn Washburn
  2020-10-27 18:03         ` Daniel Kiper
  1 sibling, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 18:01 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:
> This should improve readability of code by providing clues as to what the
> value represents.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 12 +++++++-----
>  include/grub/types.h        |  3 +++
>  2 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 623f0f396..1a91c2d55 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> +	  /* The IV is the 64 bit byte offset of the sector. */
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
> +					       - log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_MAX(iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 035a4b528..8b4267ebd 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
>  
>  #define GRUB_CHAR_BIT 8
>  
> +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)

Hum. I'd rather name this `GRUB_TYPE_BITS`, as the current name implies
that we only get a single bit. Other than that the change looks good to
me and I agree that it helps readability.

Patrick

> +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)
> +
>  #endif /* ! GRUB_TYPES_HEADER */
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-19 23:09       ` [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-10-23 18:01         ` Patrick Steinhardt
  2020-10-27 18:09           ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 18:01 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:58PM -0500, Glenn Washburn wrote:
> This makes it more obvious to the reader that the disk referred to is the
> source disk, as opposed to say the disk holding the cryptodisk.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

> ---
>  grub-core/disk/luks2.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index cd573208a..ccb94e80d 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -417,7 +417,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
>  
>  static grub_err_t
>  luks2_decrypt_key (grub_uint8_t *out_key,
> -		   grub_disk_t disk, grub_cryptodisk_t crypt,
> +		   grub_disk_t source, grub_cryptodisk_t crypt,
>  		   grub_luks2_keyslot_t *k,
>  		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
>  {
> @@ -493,7 +493,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>      }
>  
>    grub_errno = GRUB_ERR_NONE;
> -  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
> +  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
>    if (ret)
>      {
>        grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
> @@ -537,7 +537,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>  }
>  
>  static grub_err_t
> -luks2_recover_key (grub_disk_t disk,
> +luks2_recover_key (grub_disk_t source,
>  		   grub_cryptodisk_t crypt)
>  {
>    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
> @@ -552,7 +552,7 @@ luks2_recover_key (grub_disk_t disk,
>    grub_json_t *json = NULL, keyslots;
>    grub_err_t ret;
>  
> -  ret = luks2_read_header (disk, &header);
> +  ret = luks2_read_header (source, &header);
>    if (ret)
>      return ret;
>  
> @@ -561,7 +561,7 @@ luks2_recover_key (grub_disk_t disk,
>        return GRUB_ERR_OUT_OF_MEMORY;
>  
>    /* Read the JSON area. */
> -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
> +  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
>  			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
>    if (ret)
>        goto err;
> @@ -578,10 +578,10 @@ luks2_recover_key (grub_disk_t disk,
>      }
>  
>    /* Get the passphrase from the user. */
> -  if (disk->partition)
> -    part = grub_partition_get_name (disk->partition);
> -  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
> -		disk->partition ? "," : "", part ? : "",
> +  if (source->partition)
> +    part = grub_partition_get_name (source->partition);
> +  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> +		source->partition ? "," : "", part ? : "",
>  		crypt->uuid);
>    if (!grub_password_get (passphrase, MAX_PASSPHRASE))
>      {
> @@ -616,12 +616,12 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
>  			       - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
> -      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
> +      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-10-19 23:09       ` [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-10-23 18:03         ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 18:03 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:52PM -0500, Glenn Washburn wrote:
> The total_length field is named confusingly because length usually refers to
> bytes, whereas in this case its really the total number of sectors on the
> device. Also counter-intuitively, grub_disk_get_size returns the total
> number of device native sectors. We need to convert the sectors from the
> size of the underlying device to the cryptodisk sector size. And
> segment.size is in bytes which need to be converted to cryptodisk sectors.
> 
> Also, removed an empty statement.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

> ---
>  grub-core/disk/luks2.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 4e1e47161..311d18684 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -425,7 +425,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>    grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
>    grub_uint8_t *split_key = NULL;
>    grub_size_t saltlen = sizeof (salt);
> -  char cipher[32], *p;;
> +  char cipher[32], *p;
>    const gcry_md_spec_t *hash;
>    gcry_err_code_t gcry_ret;
>    grub_err_t ret;
> @@ -611,9 +611,10 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
> +	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
> +			       - crypt->offset;
>        else
> -	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-19 23:09       ` [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-10-23 18:09         ` Patrick Steinhardt
  2020-10-26 15:43           ` Daniel Kiper
  2020-10-30 20:47         ` Daniel Kiper
  1 sibling, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-23 18:09 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
> 
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
> 
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 47 insertions(+), 25 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index a3d672f68..623f0f396 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>  
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>  
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> +	      iv[1] = 0;
> +	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> +	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>  				    & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> @@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_CBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_PCBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (err)
>  	      return err;
>  	    
> -	    for (j = 0; j < (1U << dev->log_sector_size);
> +	    for (j = 0; j < (1U << log_sector_size);
>  		 j += dev->cipher->cipher->blocksize)
>  	      {
>  		grub_crypto_xor (data + i + j, data + i + j, iv,
> @@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (do_encrypt)
>  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    else
>  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    if (err)
>  	      return err;
>  	    lrw_xor (&sec, dev, data + i);
> @@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_ECB:
>  	  if (do_encrypt)
>  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  else
>  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector)
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
>  {
> -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
>  }
>  
>  grub_err_t
> @@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
>  					size << disk->log_sector_size,
> -					sector, 0);
> +					sector, dev->log_sector_size, 0);
>    return grub_crypto_gcry_error (gcry_err);
>  }
>  
> @@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> -					sector, 1);
> +					sector, disk->log_sector_size, 1);
>    if (gcry_err)
>      {
>        grub_free (tmp);
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 59702067a..20cc20b9b 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
> -  newdev->log_sector_size = 9;
> +  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
>    newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
> @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
>  	  return err;
>  	}
>  
> -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> +					  LUKS1_LOG_SECTOR_SIZE);
>        if (gcry_err)
>  	{
>  	  grub_free (split_key);
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 311d18684..b9e0e98e1 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -500,7 +500,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>        goto err;
>      }
>  
> -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> +  /*
> +   * The key slots area is always encrypted in 512-byte sectors,
> +   * regardless of encrypted data sector size.
> +   */
> +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> +				      LUKS1_LOG_SECTOR_SIZE);
>    if (gcry_ret)
>      {
>        ret = grub_crypto_gcry_error (gcry_ret);
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index e1b21e785..006f3ec49 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -48,6 +48,12 @@ typedef enum
>  
>  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
>  
> +/* LUKS1 specification defines the block size to always be 512 bytes. */
> +#define LUKS1_LOG_SECTOR_SIZE 9

Nit: This should probably be called `GRUB_LUKS1_LOG_SECTOR_SIZE`.
Otherwise the patch looks good to me.

Patrick

> +/* By default dm-crypt increments the IV every 512 bytes. */
> +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> +
>  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
>  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
> @@ -139,7 +145,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector);
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size);
>  grub_err_t
>  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
>  			grub_disk_t source);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-23 18:09         ` Patrick Steinhardt
@ 2020-10-26 15:43           ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-26 15:43 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Fri, Oct 23, 2020 at 08:09:10PM +0200, Patrick Steinhardt wrote:
> On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> > By default, dm-crypt internally uses an IV that corresponds to 512-byte
> > sectors, even when a larger sector size is specified. What this means is
> > that when using a larger sector size, the IV is incremented every sector.
> > However, the amount the IV is incremented is the number of 512 byte blocks
> > in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> > the number of, for example, 4K sectors. So each 512 byte cipher block in a
> > sector will be encrypted with the same IV and the IV will be incremented
> > afterwards by the number of 512 byte cipher blocks in the sector.
> >
> > There are some encryption utilities which do it the intuitive way and have
> > the IV equal to the sector number regardless of sector size (ie. the fifth
> > sector would have an IV of 4 for each cipher block). And this is supported
> > by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> > with the --iv-large-sectors, though not with LUKS headers (only with --type
> > plain). However, support for this has not been included as grub does not
> > support plain devices right now.
> >
> > One gotcha here is that the encrypted split keys are encrypted with a hard-
> > coded 512-byte sector size. So even if your data is encrypted with 4K sector
> > sizes, the split key encrypted area must be decrypted with a block size of
> > 512 (ie the IV increments every 512 bytes). This made these changes less
> > aestetically pleasing than desired.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
> >  grub-core/disk/luks.c       |  5 ++--
> >  grub-core/disk/luks2.c      |  7 ++++-
> >  include/grub/cryptodisk.h   |  8 +++++-
> >  4 files changed, 47 insertions(+), 25 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> > index a3d672f68..623f0f396 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> >  static gcry_err_code_t
> >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  			   grub_uint8_t * data, grub_size_t len,
> > -			   grub_disk_addr_t sector, int do_encrypt)
> > +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> > +			   int do_encrypt)
> >  {
> >    grub_size_t i;
> >    gcry_err_code_t err;
> > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
> >  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
> >
> > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > +  for (i = 0; i < len; i += (1U << log_sector_size))
> >      {
> >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> >  			 + sizeof (grub_uint32_t) - 1)
> > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	    if (!ctx)
> >  	      return GPG_ERR_OUT_OF_MEMORY;
> >
> > -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> >  	    dev->iv_hash->init (ctx);
> >  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
> >  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	  }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > -	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  /*
> > +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> > +	   * number. If using 32 bit IV mode, zero out the most significant
> > +	   * 32 bits.
> > +	   */
> > +	  {
> > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> > +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> > +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> > +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> > +	      iv[1] = 0;
> > +	  }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> > -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> > +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> >  				    & 0xFFFFFFFF);
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> > @@ -311,10 +321,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	case GRUB_CRYPTODISK_MODE_CBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> > -					   (1U << dev->log_sector_size), iv);
> > +					   (1U << log_sector_size), iv);
> >  	  else
> >  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> > -					   (1U << dev->log_sector_size), iv);
> > +					   (1U << log_sector_size), iv);
> >  	  if (err)
> >  	    return err;
> >  	  break;
> > @@ -322,10 +332,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	case GRUB_CRYPTODISK_MODE_PCBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> > -					    (1U << dev->log_sector_size), iv);
> > +					    (1U << log_sector_size), iv);
> >  	  else
> >  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> > -					    (1U << dev->log_sector_size), iv);
> > +					    (1U << log_sector_size), iv);
> >  	  if (err)
> >  	    return err;
> >  	  break;
> > @@ -337,7 +347,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	    if (err)
> >  	      return err;
> >
> > -	    for (j = 0; j < (1U << dev->log_sector_size);
> > +	    for (j = 0; j < (1U << log_sector_size);
> >  		 j += dev->cipher->cipher->blocksize)
> >  	      {
> >  		grub_crypto_xor (data + i + j, data + i + j, iv,
> > @@ -368,11 +378,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	    if (do_encrypt)
> >  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
> >  					     data + i,
> > -					     (1U << dev->log_sector_size));
> > +					     (1U << log_sector_size));
> >  	    else
> >  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
> >  					     data + i,
> > -					     (1U << dev->log_sector_size));
> > +					     (1U << log_sector_size));
> >  	    if (err)
> >  	      return err;
> >  	    lrw_xor (&sec, dev, data + i);
> > @@ -381,10 +391,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  	case GRUB_CRYPTODISK_MODE_ECB:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> > -					   (1U << dev->log_sector_size));
> > +					   (1U << log_sector_size));
> >  	  else
> >  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> > -					   (1U << dev->log_sector_size));
> > +					   (1U << log_sector_size));
> >  	  if (err)
> >  	    return err;
> >  	  break;
> > @@ -399,9 +409,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  gcry_err_code_t
> >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> >  			 grub_uint8_t * data, grub_size_t len,
> > -			 grub_disk_addr_t sector)
> > +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
> >  {
> > -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> > +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
> >  }
> >
> >  grub_err_t
> > @@ -766,7 +776,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
> >      }
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
> >  					size << disk->log_sector_size,
> > -					sector, 0);
> > +					sector, dev->log_sector_size, 0);
> >    return grub_crypto_gcry_error (gcry_err);
> >  }
> >
> > @@ -807,7 +817,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
> >
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
> >  					size << disk->log_sector_size,
> > -					sector, 1);
> > +					sector, disk->log_sector_size, 1);
> >    if (gcry_err)
> >      {
> >        grub_free (tmp);
> > diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> > index 59702067a..20cc20b9b 100644
> > --- a/grub-core/disk/luks.c
> > +++ b/grub-core/disk/luks.c
> > @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
> >        return NULL;
> >    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> >    newdev->source_disk = NULL;
> > -  newdev->log_sector_size = 9;
> > +  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
> >    newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> >    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
> >    newdev->modname = "luks";
> > @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
> >  	  return err;
> >  	}
> >
> > -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> > +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> > +					  LUKS1_LOG_SECTOR_SIZE);
> >        if (gcry_err)
> >  	{
> >  	  grub_free (split_key);
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 311d18684..b9e0e98e1 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -500,7 +500,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> >        goto err;
> >      }
> >
> > -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> > +  /*
> > +   * The key slots area is always encrypted in 512-byte sectors,
> > +   * regardless of encrypted data sector size.
> > +   */
> > +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> > +				      LUKS1_LOG_SECTOR_SIZE);
> >    if (gcry_ret)
> >      {
> >        ret = grub_crypto_gcry_error (gcry_ret);
> > diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> > index e1b21e785..006f3ec49 100644
> > --- a/include/grub/cryptodisk.h
> > +++ b/include/grub/cryptodisk.h
> > @@ -48,6 +48,12 @@ typedef enum
> >
> >  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
> >
> > +/* LUKS1 specification defines the block size to always be 512 bytes. */
> > +#define LUKS1_LOG_SECTOR_SIZE 9
>
> Nit: This should probably be called `GRUB_LUKS1_LOG_SECTOR_SIZE`.

Yep.

> Otherwise the patch looks good to me.

Same for me, Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

I can fix this minor issue before committing the patch.

Daniel


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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-23 18:01         ` Patrick Steinhardt
@ 2020-10-26 18:25           ` Glenn Washburn
  2020-10-28 18:16             ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-26 18:25 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

Oct 23, 2020 1:00:59 PM Patrick Steinhardt <ps@pks.im>:

> On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:
>> This should improve readability of code by providing clues as to what the
>> value represents.
>>
>> Signed-off-by: Glenn Washburn <development@efficientek.com>
>> ---
>> grub-core/disk/cryptodisk.c | 12 +++++++-----
>> include/grub/types.h        |  3 +++
>> 2 files changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
>> index 623f0f396..1a91c2d55 100644
>> --- a/grub-core/disk/cryptodisk.c
>> +++ b/grub-core/disk/cryptodisk.c
>> @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>> }
>> break;
>> case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
>> -   iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
>> +   /* The IV is the 64 bit byte offset of the sector. */
>> +   iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
>> +                - log_sector_size));
>> iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>> -           & 0xFFFFFFFF);
>> +           & GRUB_TYPE_MAX(iv[0]));
>> break;
>> case GRUB_CRYPTODISK_MODE_IV_BENBI:
>> {
>> grub_uint64_t num = (sector << dev->benbi_log) + 1;
>> -     iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
>> -     iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
>> +     iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
>> +     iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
>> }
>> break;
>> case GRUB_CRYPTODISK_MODE_IV_ESSIV:
>> -   iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
>> +   iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
>> err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>> dev->cipher->cipher->blocksize);
>> if (err)
>> diff --git a/include/grub/types.h b/include/grub/types.h
>> index 035a4b528..8b4267ebd 100644
>> --- a/include/grub/types.h
>> +++ b/include/grub/types.h
>> @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
>>
>> #define GRUB_CHAR_BIT 8
>>
>> +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
>
> Hum. I'd rather name this `GRUB_TYPE_BITS`, as the current name implies
> that we only get a single bit. Other than that the change looks good to
> me and I agree that it helps readability.
>
> Patrick

Yes, I would've liked to also, but I decided to stick with the naming convention as can be seen in the definition of GRUB_CHAR_BIT above it. Should there be a separate patch renaming GRUB_CHAR_BIT also?

>
>> +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)
>> +
>> #endif /* ! GRUB_TYPES_HEADER */
>> --
>> 2.27.0
>>



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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-19 23:09       ` [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
  2020-10-23 18:01         ` Patrick Steinhardt
@ 2020-10-27 18:03         ` Daniel Kiper
  2020-10-29 21:51           ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-10-27 18:03 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:
> This should improve readability of code by providing clues as to what the
> value represents.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 12 +++++++-----
>  include/grub/types.h        |  3 +++
>  2 files changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 623f0f396..1a91c2d55 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> +	  /* The IV is the 64 bit byte offset of the sector. */
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])

Missing space between macro name and "(".

> +					       - log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_MAX(iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));

Ditto.

> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));

Ditto.

>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));

Ditto.

>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 035a4b528..8b4267ebd 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
>
>  #define GRUB_CHAR_BIT 8

I think we should not change the name of this constant. It seems to me that
it was named in similar way to C/gcc/clang CHAR_BIT and/or __CHAR_BIT__.
However, I think we should change its definition. It should be

  #define GRUB_CHAR_BIT __CHAR_BIT__

Additionally, the build should stop if __CHAR_BIT__ is not defined nor
GRUB_CHAR_BIT is not equal 8.

Last but not least, the GRUB_CHAR_BIT definition should be right behind includes
in the include/grub/types.h.

> +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)

I agree with Patrick, it should be named GRUB_TYPE_BITS.

> +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) - 1)) - 1)) + 1)

This only works for unsigned types. So, I think we should have three
(four?) macros here: (GRUB_TYPE_U_MIN? (which is obviously 0)),
GRUB_TYPE_U_MAX, GRUB_TYPE_S_MIN and GRUB_TYPE_S_MAX.

Daniel


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

* Re: [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-10-23 17:58         ` Patrick Steinhardt
@ 2020-10-27 18:06           ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-27 18:06 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Glenn Washburn

On Fri, Oct 23, 2020 at 07:58:50PM +0200, Patrick Steinhardt wrote:
> On Mon, Oct 19, 2020 at 06:09:56PM -0500, Glenn Washburn wrote:
> > This creates an alignment with grub_disk_t naming of the same field and is
> > more intuitive as to how it should be used.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-10-23 17:58         ` Patrick Steinhardt
@ 2020-10-27 18:07           ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-27 18:07 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Glenn Washburn

On Fri, Oct 23, 2020 at 07:58:13PM +0200, Patrick Steinhardt wrote:
> On Mon, Oct 19, 2020 at 06:09:57PM -0500, Glenn Washburn wrote:
> > This makes it clear that the offset represents sectors, not bytes, in order
> > to improve readability.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-10-23 18:01         ` Patrick Steinhardt
@ 2020-10-27 18:09           ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-27 18:09 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Glenn Washburn

On Fri, Oct 23, 2020 at 08:01:54PM +0200, Patrick Steinhardt wrote:
> On Mon, Oct 19, 2020 at 06:09:58PM -0500, Glenn Washburn wrote:
> > This makes it more obvious to the reader that the disk referred to is the
> > source disk, as opposed to say the disk holding the cryptodisk.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (9 preceding siblings ...)
  2020-10-19 23:09       ` [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-10-27 19:25       ` Daniel Kiper
  2020-11-02 15:56         ` Daniel Kiper
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
  11 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-10-27 19:25 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:48PM -0500, Glenn Washburn wrote:
> Heres an updated patch series which addresses comment from Patrick. The only
> code change is adding a slot_key member to grub_luks2_keyslot and using that
> instead of an extra out parameter to luks2_get_keyslot.
>
> Glenn Washburn (10):
>   luks2: Fix use of incorrect index and some grub_error() messages.
>   luks2: Improve readability in luks2_get_keyslot.
>   luks2: Use more intuitive keyslot key instead of index when naming
>     keyslot.
>   luks2: grub_cryptodisk_t->total_length is the max number of device
>     native sectors
>   cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
>   cryptodisk: Properly handle non-512 byte sized sectors.
>   cryptodisk: Replace some literals with constants in
>     grub_cryptodisk_endecrypt.
>   cryptodisk: Rename total_length field in grub_cryptodisk_t to
>     total_sectors.
>   cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
>   luks2: Rename source disk variabled named 'disk' to 'source' as in
>     luks.c.

Most of LUKS2 patches require rework. The rest which got Patrick's and
my RB I will push into the GRUB git repo by the end of this week. Of
course if there are no objections...

Daniel


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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-26 18:25           ` Glenn Washburn
@ 2020-10-28 18:16             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-10-28 18:16 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Oct 26, 2020 at 06:25:53PM +0000, Glenn Washburn wrote:
> Oct 23, 2020 1:00:59 PM Patrick Steinhardt <ps@pks.im>:
> 
> > On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:
> >> This should improve readability of code by providing clues as to what the
> >> value represents.
> >>
> >> Signed-off-by: Glenn Washburn <development@efficientek.com>
> >> ---
> >> grub-core/disk/cryptodisk.c | 12 +++++++-----
> >> include/grub/types.h        |  3 +++
> >> 2 files changed, 10 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> >> index 623f0f396..1a91c2d55 100644
> >> --- a/grub-core/disk/cryptodisk.c
> >> +++ b/grub-core/disk/cryptodisk.c
> >> @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >> }
> >> break;
> >> case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> >> -   iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
> >> +   /* The IV is the 64 bit byte offset of the sector. */
> >> +   iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
> >> +                - log_sector_size));
> >> iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> >> -           & 0xFFFFFFFF);
> >> +           & GRUB_TYPE_MAX(iv[0]));
> >> break;
> >> case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >> {
> >> grub_uint64_t num = (sector << dev->benbi_log) + 1;
> >> -     iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> >> -     iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> >> +     iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BIT(iv[0]));
> >> +     iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_MAX(iv[0]));
> >> }
> >> break;
> >> case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> >> -   iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> >> +   iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
> >> err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >> dev->cipher->cipher->blocksize);
> >> if (err)
> >> diff --git a/include/grub/types.h b/include/grub/types.h
> >> index 035a4b528..8b4267ebd 100644
> >> --- a/include/grub/types.h
> >> +++ b/include/grub/types.h
> >> @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
> >>
> >> #define GRUB_CHAR_BIT 8
> >>
> >> +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
> >
> > Hum. I'd rather name this `GRUB_TYPE_BITS`, as the current name implies
> > that we only get a single bit. Other than that the change looks good to
> > me and I agree that it helps readability.
> >
> > Patrick
> 
> Yes, I would've liked to also, but I decided to stick with the naming
> convention as can be seen in the definition of GRUB_CHAR_BIT above it.
> Should there be a separate patch renaming GRUB_CHAR_BIT also?

Nah, your naming makes sense in that context. Let's keep it as-is in
this patch.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-27 18:03         ` Daniel Kiper
@ 2020-10-29 21:51           ` Glenn Washburn
  2020-10-30 13:11             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-29 21:51 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Tue, 27 Oct 2020 19:03:36 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:
> > This should improve readability of code by providing clues as to
> > what the value represents.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 12 +++++++-----
> >  include/grub/types.h        |  3 +++
> >  2 files changed, 10 insertions(+), 5 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index 623f0f396..1a91c2d55 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -297,19 +297,21 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > log_sector_size));
> > +	  /* The IV is the 64 bit byte offset of the sector. */
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BIT(iv[0])
> 
> Missing space between macro name and "(".
> 
> > +					       - log_sector_size));
> >  	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> > -				    & 0xFFFFFFFF);
> > +				    & GRUB_TYPE_MAX(iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >  	  {
> >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> > -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > +	    iv[sz - 2] = grub_cpu_to_be32 (num >>
> > GRUB_TYPE_BIT(iv[0]));
> 
> Ditto.
> 
> > +	    iv[sz - 1] = grub_cpu_to_be32 (num &
> > GRUB_TYPE_MAX(iv[0]));
> 
> Ditto.
> 
> >  	  }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_MAX(iv[0]));
> 
> Ditto.
> 
> >  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >  					 dev->cipher->cipher->blocksize);
> >  	  if (err)
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index 035a4b528..8b4267ebd 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void
> > *ptr, grub_uint64_t val)
> >
> >  #define GRUB_CHAR_BIT 8
> 
> I think we should not change the name of this constant. It seems to
> me that it was named in similar way to C/gcc/clang CHAR_BIT and/or
> __CHAR_BIT__. However, I think we should change its definition. It
> should be
> 
>   #define GRUB_CHAR_BIT __CHAR_BIT__

I can add that into this commit.

> Additionally, the build should stop if __CHAR_BIT__ is not defined nor
> GRUB_CHAR_BIT is not equal 8.

I'm not sure exactly how you want that done.

> Last but not least, the GRUB_CHAR_BIT definition should be right
> behind includes in the include/grub/types.h.
> 
> > +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
> 
> I agree with Patrick, it should be named GRUB_TYPE_BITS.

Patrick says my logic makes sense for him.  I can still change it, yes?

> > +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) -
> > 1)) - 1)) + 1)
> 
> This only works for unsigned types. So, I think we should have three
> (four?) macros here: (GRUB_TYPE_U_MIN? (which is obviously 0)),
> GRUB_TYPE_U_MAX, GRUB_TYPE_S_MIN and GRUB_TYPE_S_MAX.

How about I just rename GRUB_TYPE_MAX to GRUB_TYPE_U_MAX and someone
(you?) can add in the rest?  I'm not sure how I'd do the signed
variants that works across all architectures.

> Daniel


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

* Re: [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-23 12:14         ` Daniel Kiper
@ 2020-10-29 21:52           ` Glenn Washburn
  2020-10-30 13:15             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-10-29 21:52 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Fri, 23 Oct 2020 14:14:52 +0200
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Mon, Oct 19, 2020 at 06:09:50PM -0500, Glenn Washburn wrote:
> > Introduce new variables keyslot_key, digest_key, and segment_key
> > which represent the integer key of the item in the respective
> > associative array when looping over the array items. This replaces
> > using a generically named variable named "idx" used for all three
> > values. The parameter "i" is renamed to "keyslot_idx" and the loop
> > variable "j" is renamed to "i". Error messages now distinguish
> > between indexes and keys.  The former include "index" in the error
> > string, and the later are surrounded in quotes.
> 
> I think this patch does too many things in one step. Please do one
> rename per patch if possible. Additionally, I think this patch, or
> series of the patches, should be before current patch #1.
> 
> Daniel

Okay, I've split these two patches into 5 patches:
5: luks2: Improve error messages in luks2_get_keyslot.
4: luks2: Split idx into three variables: keyslot_key, digest_key,
   segment_key. 
3: luks2: Rename index variable j to i.
2: luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
1: luks2: Use correct index variable when looping in luks2_get_keyslot.

I'm traveling the next few days and thinking that it would be best to
send these with the next iteration of the patch series which includes
some of the changes suggested for other patches.

Glenn


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

* Re: [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-10-29 21:51           ` Glenn Washburn
@ 2020-10-30 13:11             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-30 13:11 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Oct 29, 2020 at 04:51:37PM -0500, Glenn Washburn wrote:
> On Tue, 27 Oct 2020 19:03:36 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
> > On Mon, Oct 19, 2020 at 06:09:55PM -0500, Glenn Washburn wrote:

[...]

> > > diff --git a/include/grub/types.h b/include/grub/types.h
> > > index 035a4b528..8b4267ebd 100644
> > > --- a/include/grub/types.h
> > > +++ b/include/grub/types.h
> > > @@ -319,4 +319,7 @@ static inline void grub_set_unaligned64 (void
> > > *ptr, grub_uint64_t val)
> > >
> > >  #define GRUB_CHAR_BIT 8
> >
> > I think we should not change the name of this constant. It seems to
> > me that it was named in similar way to C/gcc/clang CHAR_BIT and/or
> > __CHAR_BIT__. However, I think we should change its definition. It
> > should be
> >
> >   #define GRUB_CHAR_BIT __CHAR_BIT__
>
> I can add that into this commit.

It has to be separate commit because it is logically different change.

> > Additionally, the build should stop if __CHAR_BIT__ is not defined nor
> > GRUB_CHAR_BIT is not equal 8.
>
> I'm not sure exactly how you want that done.

#ifndef __CHAR_BIT__
#error __CHAR_BIT__ is not defined
#else __CHAR_BIT__ != 8
#error __CHAR_BIT__ is not equal 8
#else
#define GRUB_CHAR_BIT __CHAR_BIT__
#endif

> > Last but not least, the GRUB_CHAR_BIT definition should be right
> > behind includes in the include/grub/types.h.
> >
> > > +#define GRUB_TYPE_BIT(type) (sizeof(type) * GRUB_CHAR_BIT)
> >
> > I agree with Patrick, it should be named GRUB_TYPE_BITS.
>
> Patrick says my logic makes sense for him.  I can still change it, yes?

Ugh... I missed his last email somehow. Sorry about that. I still think
it should be GRUB_TYPE_BITS(). So, please rename GRUB_TYPE_BIT() to
GRUB_TYPE_BITS(). GRUB_CHAR_BIT name should stay as is.

> > > +#define GRUB_TYPE_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BIT(type) -
> > > 1)) - 1)) + 1)
> >
> > This only works for unsigned types. So, I think we should have three
> > (four?) macros here: (GRUB_TYPE_U_MIN? (which is obviously 0)),
> > GRUB_TYPE_U_MAX, GRUB_TYPE_S_MIN and GRUB_TYPE_S_MAX.
>
> How about I just rename GRUB_TYPE_MAX to GRUB_TYPE_U_MAX and someone
> (you?) can add in the rest?  I'm not sure how I'd do the signed
> variants that works across all architectures.

I am not going to insist on adding GRUB_TYPE_S_MIN/GRUB_TYPE_S_MAX if
you think it is complicated. Though please rename GRUB_TYPE_MAX to
GRUB_TYPE_U_MAX.

Daniel


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

* Re: [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot.
  2020-10-29 21:52           ` Glenn Washburn
@ 2020-10-30 13:15             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-10-30 13:15 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Oct 29, 2020 at 04:52:55PM -0500, Glenn Washburn wrote:
> On Fri, 23 Oct 2020 14:14:52 +0200
> Daniel Kiper <dkiper@net-space.pl> wrote:
> > On Mon, Oct 19, 2020 at 06:09:50PM -0500, Glenn Washburn wrote:
> > > Introduce new variables keyslot_key, digest_key, and segment_key
> > > which represent the integer key of the item in the respective
> > > associative array when looping over the array items. This replaces
> > > using a generically named variable named "idx" used for all three
> > > values. The parameter "i" is renamed to "keyslot_idx" and the loop
> > > variable "j" is renamed to "i". Error messages now distinguish
> > > between indexes and keys.  The former include "index" in the error
> > > string, and the later are surrounded in quotes.
> >
> > I think this patch does too many things in one step. Please do one
> > rename per patch if possible. Additionally, I think this patch, or
> > series of the patches, should be before current patch #1.
> >
> > Daniel
>
> Okay, I've split these two patches into 5 patches:
> 5: luks2: Improve error messages in luks2_get_keyslot.
> 4: luks2: Split idx into three variables: keyslot_key, digest_key,
>    segment_key.
> 3: luks2: Rename index variable j to i.
> 2: luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
> 1: luks2: Use correct index variable when looping in luks2_get_keyslot.

LGTM...

> I'm traveling the next few days and thinking that it would be best to
> send these with the next iteration of the patch series which includes
> some of the changes suggested for other patches.

Yeah, that would be perfect.

Thank you for doing the work.

Have a nice weekend,

Daniel


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-19 23:09       ` [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
  2020-10-23 18:09         ` Patrick Steinhardt
@ 2020-10-30 20:47         ` Daniel Kiper
  2020-11-06 19:08           ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-10-30 20:47 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
>
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
>
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++---------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 47 insertions(+), 25 deletions(-)
>
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index a3d672f68..623f0f396 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;

./configure --target=arm-linux-gnueabihf --with-platform=coreboot ...
make

...and you get this:

  disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
  disk/cryptodisk.c:292:28: error: cast increases required alignment of target type [-Werror=cast-align]
        grub_uint64_t *iv64 = (grub_uint64_t *)iv;
                              ^
  cc1: all warnings being treated as errors

I think every 32-bit build will/may fail. It seems to me that
  (grub_uint64_t *)(void *) iv;
or
  (grub_uint64_t *)(grub_addr_t) iv;
should help.

Daniel


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

* Re: [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux
  2020-10-27 19:25       ` [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux Daniel Kiper
@ 2020-11-02 15:56         ` Daniel Kiper
  2020-11-03 18:50           ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-02 15:56 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Oct 27, 2020 at 08:25:13PM +0100, Daniel Kiper wrote:
> On Mon, Oct 19, 2020 at 06:09:48PM -0500, Glenn Washburn wrote:
> > Heres an updated patch series which addresses comment from Patrick. The only
> > code change is adding a slot_key member to grub_luks2_keyslot and using that
> > instead of an extra out parameter to luks2_get_keyslot.
> >
> > Glenn Washburn (10):
> >   luks2: Fix use of incorrect index and some grub_error() messages.
> >   luks2: Improve readability in luks2_get_keyslot.
> >   luks2: Use more intuitive keyslot key instead of index when naming
> >     keyslot.
> >   luks2: grub_cryptodisk_t->total_length is the max number of device
> >     native sectors
> >   cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
> >   cryptodisk: Properly handle non-512 byte sized sectors.
> >   cryptodisk: Replace some literals with constants in
> >     grub_cryptodisk_endecrypt.
> >   cryptodisk: Rename total_length field in grub_cryptodisk_t to
> >     total_sectors.
> >   cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
> >   luks2: Rename source disk variabled named 'disk' to 'source' as in
> >     luks.c.
>
> Most of LUKS2 patches require rework. The rest which got Patrick's and
> my RB I will push into the GRUB git repo by the end of this week. Of
> course if there are no objections...

I was only able to take 'cryptodisk: Fix cipher IV mode "plain64" always
being set as "plain"' patch. The other patches depend on some changes in
earlier patches in the series. So, feel free to add my RB to the patches
which got it from me.

Daniel


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

* Re: [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux
  2020-11-02 15:56         ` Daniel Kiper
@ 2020-11-03 18:50           ` Glenn Washburn
  2020-11-04 12:44             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-03 18:50 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

Nov 2, 2020 9:56:58 AM Daniel Kiper <dkiper@net-space.pl>:

> On Tue, Oct 27, 2020 at 08:25:13PM +0100, Daniel Kiper wrote:
>> On Mon, Oct 19, 2020 at 06:09:48PM -0500, Glenn Washburn wrote:
>>> Heres an updated patch series which addresses comment from Patrick. The only
>>> code change is adding a slot_key member to grub_luks2_keyslot and using that
>>> instead of an extra out parameter to luks2_get_keyslot.
>>>
>>> Glenn Washburn (10):
>>> luks2: Fix use of incorrect index and some grub_error() messages.
>>> luks2: Improve readability in luks2_get_keyslot.
>>> luks2: Use more intuitive keyslot key instead of index when naming
>>> keyslot.
>>> luks2: grub_cryptodisk_t->total_length is the max number of device
>>> native sectors
>>> cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
>>> cryptodisk: Properly handle non-512 byte sized sectors.
>>> cryptodisk: Replace some literals with constants in
>>> grub_cryptodisk_endecrypt.
>>> cryptodisk: Rename total_length field in grub_cryptodisk_t to
>>> total_sectors.
>>> cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
>>> luks2: Rename source disk variabled named 'disk' to 'source' as in
>>> luks.c.
>>
>> Most of LUKS2 patches require rework. The rest which got Patrick's and
>> my RB I will push into the GRUB git repo by the end of this week. Of
>> course if there are no objections...
>
> I was only able to take 'cryptodisk: Fix cipher IV mode "plain64" always
> being set as "plain"' patch. The other patches depend on some changes in
> earlier patches in the series. So, feel free to add my RB to the patches
> which got it from me.
>
> Daniel
>

If I move the rework the rename patches to be earlier in the patch series, you should be able to get those in right? It's annoying to keep them in the patch series while reworking the other patches.

Glenn



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

* Re: [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux
  2020-11-03 18:50           ` Glenn Washburn
@ 2020-11-04 12:44             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-04 12:44 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Nov 03, 2020 at 06:50:56PM +0000, Glenn Washburn wrote:
> Nov 2, 2020 9:56:58 AM Daniel Kiper <dkiper@net-space.pl>:
> > On Tue, Oct 27, 2020 at 08:25:13PM +0100, Daniel Kiper wrote:
> >> On Mon, Oct 19, 2020 at 06:09:48PM -0500, Glenn Washburn wrote:
> >>> Heres an updated patch series which addresses comment from Patrick. The only
> >>> code change is adding a slot_key member to grub_luks2_keyslot and using that
> >>> instead of an extra out parameter to luks2_get_keyslot.
> >>>
> >>> Glenn Washburn (10):
> >>> luks2: Fix use of incorrect index and some grub_error() messages.
> >>> luks2: Improve readability in luks2_get_keyslot.
> >>> luks2: Use more intuitive keyslot key instead of index when naming
> >>> keyslot.
> >>> luks2: grub_cryptodisk_t->total_length is the max number of device
> >>> native sectors
> >>> cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
> >>> cryptodisk: Properly handle non-512 byte sized sectors.
> >>> cryptodisk: Replace some literals with constants in
> >>> grub_cryptodisk_endecrypt.
> >>> cryptodisk: Rename total_length field in grub_cryptodisk_t to
> >>> total_sectors.
> >>> cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
> >>> luks2: Rename source disk variabled named 'disk' to 'source' as in
> >>> luks.c.
> >>
> >> Most of LUKS2 patches require rework. The rest which got Patrick's and
> >> my RB I will push into the GRUB git repo by the end of this week. Of
> >> course if there are no objections...
> >
> > I was only able to take 'cryptodisk: Fix cipher IV mode "plain64" always
> > being set as "plain"' patch. The other patches depend on some changes in
> > earlier patches in the series. So, feel free to add my RB to the patches
> > which got it from me.
> >
> > Daniel
>
> If I move the rework the rename patches to be earlier in the patch
> series, you should be able to get those in right? It's annoying to
> keep them in the patch series while reworking the other patches.

Yeah, it should help. Anyway, I think you can put all the patches with RB
at the beginning of the series. Then I will take them without any issues.

Daniel


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-10-30 20:47         ` Daniel Kiper
@ 2020-11-06 19:08           ` Glenn Washburn
  2020-11-19 14:25             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-06 19:08 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Fri, 30 Oct 2020 21:47:14 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> > By default, dm-crypt internally uses an IV that corresponds to
> > 512-byte sectors, even when a larger sector size is specified. What
> > this means is that when using a larger sector size, the IV is
> > incremented every sector. However, the amount the IV is incremented
> > is the number of 512 byte blocks in a sector (ie 8 for 4K sectors).
> > Confusingly the IV does not corespond to the number of, for
> > example, 4K sectors. So each 512 byte cipher block in a sector will
> > be encrypted with the same IV and the IV will be incremented
> > afterwards by the number of 512 byte cipher blocks in the sector.
> >
> > There are some encryption utilities which do it the intuitive way
> > and have the IV equal to the sector number regardless of sector
> > size (ie. the fifth sector would have an IV of 4 for each cipher
> > block). And this is supported by dm-crypt with the iv_large_sectors
> > option and also cryptsetup as of 2.3.3 with the --iv-large-sectors,
> > though not with LUKS headers (only with --type plain). However,
> > support for this has not been included as grub does not support
> > plain devices right now.
> >
> > One gotcha here is that the encrypted split keys are encrypted with
> > a hard- coded 512-byte sector size. So even if your data is
> > encrypted with 4K sector sizes, the split key encrypted area must
> > be decrypted with a block size of 512 (ie the IV increments every
> > 512 bytes). This made these changes less aestetically pleasing than
> > desired.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 52
> > ++++++++++++++++++++++--------------- grub-core/disk/luks.c       |
> >  5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> >  include/grub/cryptodisk.h   |  8 +++++-
> >  4 files changed, 47 insertions(+), 25 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> >  static gcry_err_code_t
> >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  			   grub_uint8_t * data, grub_size_t len,
> > -			   grub_disk_addr_t sector, int do_encrypt)
> > +			   grub_disk_addr_t sector, grub_size_t
> > log_sector_size,
> > +			   int do_encrypt)
> >  {
> >    grub_size_t i;
> >    gcry_err_code_t err;
> > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, return (do_encrypt ? grub_crypto_ecb_encrypt
> > (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt
> > (dev->cipher, data, data, len));
> >
> > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > +  for (i = 0; i < len; i += (1U << log_sector_size))
> >      {
> >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> >  			 + sizeof (grub_uint32_t) - 1)
> > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (!ctx)
> >  	      return GPG_ERR_OUT_OF_MEMORY;
> >
> > -	    tmp = grub_cpu_to_le64 (sector <<
> > dev->log_sector_size);
> > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> >  	    dev->iv_hash->init (ctx);
> >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > -	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  /*
> > +	   * The IV is a 32 or 64 bit value of the dm-crypt native
> > sector
> > +	   * number. If using 32 bit IV mode, zero out the most
> > significant
> > +	   * 32 bits.
> > +	   */
> > +	  {
> > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> 
> ./configure --target=arm-linux-gnueabihf --with-platform=coreboot ...
> make
> 
> ...and you get this:
> 
>   disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
>   disk/cryptodisk.c:292:28: error: cast increases required alignment
> of target type [-Werror=cast-align] grub_uint64_t *iv64 =
> (grub_uint64_t *)iv; ^
>   cc1: all warnings being treated as errors
> 
> I think every 32-bit build will/may fail. It seems to me that
>   (grub_uint64_t *)(void *) iv;
> or
>   (grub_uint64_t *)(grub_addr_t) iv;
> should help.

I'm having issues building for arm-linux-gnueabihf, so I can't
effectively test this.  This code does compile for
--target=i386 --with-platform=pc, which I believe is 32-bit.

Since I can't test your suggestion, I can't verify that it works.
However, I suspect it may get rid of the compiler problem, but not
solve the underlying issue, which is that iv may not be 8-byte aligned.
My guess is that if the compiler message goes away you could get a
crash at the next line if iv is not 8-byte aligned.  Can you see if the
warning disappears if you define iv like this:

  grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
  __attribute__((aligned(sizeof(grub_uint64_t))));

I'm not sure the best way to handle this the "grub way". Do you see a
better way to do this?

Glenn


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

* [PATCH v4 00/15] Cryptodisk fixes for v2.06 redux
  2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
                         ` (10 preceding siblings ...)
  2020-10-27 19:25       ` [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux Daniel Kiper
@ 2020-11-07  4:44       ` Glenn Washburn
  2020-11-07  4:44         ` [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
                           ` (19 more replies)
  11 siblings, 20 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Here we go again. I have not added RB sigs to any patches since I've had to
modify them in moving them earlier in the patch set.  This would be the first
three rename patches. The first two patches of v3 have been reworked into 5
patches (05-09) which combine to be equivalent. Most of the changes since v3 are
added error handling around luks2 cryptodisk setup. Also, I addressed an IV
alignment issue in grub_cryptodisk_endecrypt for the
GRUB_CRYPTODISK_MODE_IV_PLAIN* case, found by Daniel. I'm not sure it works
(I can't reproduce the build error) or that its the desired way of doing it.

Glenn

Glenn Washburn (15):
  cryptodisk: Rename total_length field in grub_cryptodisk_t to
    total_sectors.
  cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  luks2: Rename source disk variabled named 'disk' to 'source' as in
    luks.c.
  types: Define GRUB_CHAR_BIT based on compiler macro instead of using
    literal.
  luks2: Use correct index variable when looping in luks2_get_keyslot.
  luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
  luks2: Rename index variable j to i.
  luks2: Split idx into three variables: keyslot_key, digest_key,
    segment_key.
  luks2: Improve error messages in luks2_get_keyslot.
  luks2: Use more intuitive keyslot key instead of index when naming
    keyslot.
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt.
  luks2: grub_cryptodisk_t->total_length is the max number of device
    native sectors
  cryptodisk: Properly handle non-512 byte sized sectors.
  luks2: Better error handling when setting up the cryptodisk.
  luks2: Error check segment.sector_size.

 grub-core/disk/cryptodisk.c |  76 ++++++++++-------
 grub-core/disk/geli.c       |   4 +-
 grub-core/disk/luks.c       |   9 +-
 grub-core/disk/luks2.c      | 165 +++++++++++++++++++++++++++---------
 include/grub/cryptodisk.h   |  18 +++-
 include/grub/misc.h         |   2 +
 include/grub/types.h        |  15 +++-
 7 files changed, 205 insertions(+), 84 deletions(-)

Range-diff against v3:
 5:  e8e069cae =  1:  90fedb50c cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain'.
 8:  28e0cac66 !  2:  d72632f3f cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
    @@ grub-core/disk/luks.c
     @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uuid,
        newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
        newdev->source_disk = NULL;
    -   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
    +   newdev->log_sector_size = 9;
     -  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
     +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
        grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
            if (grub_strcmp (segment.size, "dynamic") == 0)
    --	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
    -+	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
    - 			       - crypt->offset;
    +-	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
    ++	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
            else
    --	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    -+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    +-	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
    ++	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
      
            ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
      			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
 9:  74c6232c9 !  3:  d79204f6c cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
    @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
     -  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
     +  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
        newdev->source_disk = NULL;
    -   newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
    +   newdev->log_sector_size = 9;
     -  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
     +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
        grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
    @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
    +       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
      
            /* Set up disk according to keyslot's segment. */
     -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
            if (grub_strcmp (segment.size, "dynamic") == 0)
    - 	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
    --			       - crypt->offset;
    -+			       - crypt->offset_sectors;
    +-	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
    ++	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
            else
    - 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    + 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
      
     
      ## include/grub/cryptodisk.h ##
10:  738fe0139 !  4:  cceded198 luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
            if (grub_strcmp (segment.size, "dynamic") == 0)
    --	crypt->total_sectors = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
    -+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
    - 			       - crypt->offset_sectors;
    +-	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
    ++	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
            else
    - 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    + 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
      
     -      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
     +      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 -:  --------- >  5:  badbd93f8 types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal.
 1:  80dd653c9 !  6:  4839ead9b luks2: Fix use of incorrect index and some grub_error() messages.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Fix use of incorrect index and some grub_error() messages.
    +    luks2: Use correct index variable when looping in luks2_get_keyslot.
     
    -    When looping over the digests and segments, the loop variable is j, but the
    -    variable i is used to index in the the digests and segments json array. The
    -    variable i is the keyslot index. Similarly, there are several grub_error()
    -    statements using the wrong index in constructing the error string.
    +    The loop variable j should be used to index the digests and segments json
    +    array, instead of the variable i, which is the keyslot index.
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
      
            if ((d->keyslots & (1 << idx)))
      	break;
    -     }
    -   if (j == size)
    --      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
    -+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, i);
    - 
    -   /* Get segment that matches the digest. */
    -   if (grub_json_getvalue (&segments, root, "segments") ||
    -       grub_json_getsize (&size, &segments))
    +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
    --  for (j = 0; j < size; j++)
    -+  for (i = j, j = 0; j < size; j++)
    +   for (j = 0; j < size; j++)
          {
     -      if (grub_json_getchild (&segment, &segments, i) ||
     +      if (grub_json_getchild (&segment, &segments, j) ||
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
      
            if ((d->segments & (1 << idx)))
      	break;
    -     }
    -   if (j == size)
    --    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
    -+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE, i);
    - 
    -   return GRUB_ERR_NONE;
    - }
 2:  e4cf8ab40 <  -:  --------- luks2: Improve readability in luks2_get_keyslot.
 -:  --------- >  7:  21b745c11 luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
 -:  --------- >  8:  21a3962b9 luks2: Rename index variable j to i.
 -:  --------- >  9:  b3b361c49 luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
 -:  --------- > 10:  8ac7af919 luks2: Improve error messages in luks2_get_keyslot.
 3:  1f65a04e0 ! 11:  31b9f0b83 luks2: Use more intuitive keyslot key instead of index when naming keyslot.
    @@ Commit message
         example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
         using the password for slot 4 to unlock the device, the messages using the
         index of the keyslot will mention keyslot 1 (its a zero-based index).
    -    Furthermore,with this change the keyslot number will align with the number
    +    Furthermore, with this change the keyslot number will align with the number
         used to reference the keyslot when using the --key-slot argument to
         cryptsetup.
     
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
        grub_int64_t key_size;
        grub_int64_t priority;
        struct
    +@@ grub-core/disk/luks2.c: typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
    + 
    + struct grub_luks2_segment
    + {
    ++  grub_uint64_t slot_key;
    +   grub_uint64_t offset;
    +   const char	*size;
    +   const char	*encryption;
    +@@ grub-core/disk/luks2.c: typedef struct grub_luks2_segment grub_luks2_segment_t;
    + 
    + struct grub_luks2_digest
    + {
    ++  grub_uint64_t slot_key;
    +   /* Both keyslots and segments are interpreted as bitfields here */
    +   grub_uint64_t	keyslots;
    +   grub_uint64_t	segments;
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
      {
        grub_json_t keyslots, keyslot, digests, digest, segments, segment;
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
      
     -      if ((d->keyslots & (1 << keyslot_key)))
    ++      d->slot_key = digest_key;
     +      if ((d->keyslots & (1 << k->slot_key)))
      	break;
          }
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
      
        /* Get segment that matches the digest. */
        if (grub_json_getvalue (&segments, root, "segments") ||
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    +           luks2_parse_segment (s, &segment))
    + 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
    + 
    ++      s->slot_key = segment_key;
    +       if ((d->segments & (1 << segment_key)))
    + 	break;
    +     }
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
            if (keyslot.priority == 0)
      	{
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
     +      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
      
            /* Set up disk according to keyslot's segment. */
    -       crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    +       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
            if (ret)
      	{
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
      	  continue;
      	}
      
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
             * TRANSLATORS: It's a cryptographic key slot: one element of an array
             * where each element is either empty or holds a key.
             */
 -:  --------- > 12:  87bafa5d9 cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
 4:  fcb72f70d ! 13:  1bc8c867c luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
    @@ grub-core/disk/luks2.c: luks2_decrypt_key (grub_uint8_t *out_key,
        const gcry_md_spec_t *hash;
        gcry_err_code_t gcry_ret;
        grub_err_t ret;
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t disk,
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
            if (grub_strcmp (segment.size, "dynamic") == 0)
    --	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
    -+	crypt->total_length = (grub_disk_get_size (disk) >> (crypt->log_sector_size - disk->log_sector_size))
    -+			       - crypt->offset;
    +-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
    ++	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
    ++			       - crypt->offset_sectors;
            else
    --	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
    -+	crypt->total_length = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    +-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
    ++	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
      
    -       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
    +       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
      			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
 6:  6fe26ba56 ! 14:  c3b6adaeb cryptodisk: Properly handle non-512 byte sized sectors.
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
          {
            grub_size_t sz = ((dev->cipher->cipher->blocksize
      			 + sizeof (grub_uint32_t) - 1)
    + 			/ sizeof (grub_uint32_t));
    +-      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
    ++      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4] __attribute__((aligned (sizeof (grub_uint64_t))));
    + 
    +       if (dev->rekey)
    + 	{
     @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
      	    if (!ctx)
      	      return GPG_ERR_OUT_OF_MEMORY;
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
     -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
     -	  /* FALLTHROUGH */
      	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
    --	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
    +-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
     +	  /*
     +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
     +	   * number. If using 32 bit IV mode, zero out the most significant
     +	   * 32 bits.
     +	   */
     +	  {
    -+	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
    ++	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
     +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
     +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
     +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
     +	  }
      	  break;
      	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
    --	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
    ++	  /* The IV is the 64 bit byte offset of the sector. */
    + 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
    +-					       - dev->log_sector_size));
     -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
    -+	  iv[1] = grub_cpu_to_le32 (sector >> (32 - log_sector_size));
    ++					       - log_sector_size));
     +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
    - 				    & 0xFFFFFFFF);
    + 				    & GRUB_TYPE_U_MAX (iv[0]));
      	  break;
      	case GRUB_CRYPTODISK_MODE_IV_BENBI:
     @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_write (grub_disk_t disk, grub_disk_
      ## grub-core/disk/luks.c ##
     @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uuid,
            return NULL;
    -   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
    +   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
        newdev->source_disk = NULL;
     -  newdev->log_sector_size = 9;
    -+  newdev->log_sector_size = LUKS1_LOG_SECTOR_SIZE;
    -   newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
    ++  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
    +   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
        grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
        newdev->modname = "luks";
     @@ grub-core/disk/luks.c: luks_recover_key (grub_disk_t source,
    @@ grub-core/disk/luks.c: luks_recover_key (grub_disk_t source,
      
     -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
     +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
    -+					  LUKS1_LOG_SECTOR_SIZE);
    ++					  GRUB_LUKS1_LOG_SECTOR_SIZE);
            if (gcry_err)
      	{
      	  grub_free (split_key);
    @@ grub-core/disk/luks2.c: luks2_decrypt_key (grub_uint8_t *out_key,
     +   * regardless of encrypted data sector size.
     +   */
     +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
    -+				      LUKS1_LOG_SECTOR_SIZE);
    ++				      GRUB_LUKS1_LOG_SECTOR_SIZE);
        if (gcry_ret)
          {
            ret = grub_crypto_gcry_error (gcry_ret);
    @@ include/grub/cryptodisk.h: typedef enum
      #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
      
     +/* LUKS1 specification defines the block size to always be 512 bytes. */
    -+#define LUKS1_LOG_SECTOR_SIZE 9
    ++#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
     +
     +/* By default dm-crypt increments the IV every 512 bytes. */
     +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
 7:  3918a9013 <  -:  --------- cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
 -:  --------- > 15:  f0758a06f luks2: Better error handling when setting up the cryptodisk.
 -:  --------- > 16:  6ef5c9965 luks2: Error check segment.sector_size.
-- 
2.27.0



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

* [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:37           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
                           ` (18 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This creates an alignment with grub_disk_t naming of the same field and is
more intuitive as to how it should be used.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 2 +-
 grub-core/disk/geli.c       | 2 +-
 grub-core/disk/luks.c       | 2 +-
 grub-core/disk/luks2.c      | 4 ++--
 include/grub/cryptodisk.h   | 3 ++-
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index a3d672f68..3703da221 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -699,7 +699,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
     }
 
   disk->data = dev;
-  disk->total_sectors = dev->total_length;
+  disk->total_sectors = dev->total_sectors;
   disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
   disk->id = dev->id;
   dev->ref++;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index e9d23299a..4ec875821 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_length = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = 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;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 59702067a..429db4ad8 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = 9;
-  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 31d7166fc..3173a098d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -609,9 +609,9 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
+	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
       else
-	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
 
       ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index e1b21e785..21dc69501 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -67,7 +67,8 @@ struct grub_cryptodisk
 
   char *source;
   grub_disk_addr_t offset;
-  grub_disk_addr_t total_length;
+  /* Total number of encrypted sectors of size (1<<log_sector_size) */
+  grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
   int ref;
   grub_crypto_cipher_handle_t cipher;
-- 
2.27.0



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

* [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
  2020-11-07  4:44         ` [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:38           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
                           ` (17 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This makes it clear that the offset represents sectors, not bytes, in order
to improve readability.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 10 +++++-----
 grub-core/disk/geli.c       |  2 +-
 grub-core/disk/luks.c       |  4 ++--
 grub-core/disk/luks2.c      |  4 ++--
 include/grub/cryptodisk.h   |  7 ++++++-
 5 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 3703da221..473c93976 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -754,10 +754,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   err = grub_disk_read (dev->source_disk,
-			grub_disk_from_native_sector (disk, sector + dev->offset),
+			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
 			0, size << disk->log_sector_size, buf);
   if (err)
     {
@@ -803,7 +803,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
   grub_dprintf ("cryptodisk",
 		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
 		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
-		size, sector, dev->offset);
+		size, sector, dev->offset_sectors);
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
@@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
     }
 
   /* Since ->write was called so disk.mod is loaded but be paranoid  */
-  sector = sector + dev->offset;
+  sector = sector + dev->offset_sectors;
   if (grub_disk_write_weak)
     err = grub_disk_write_weak (dev->source_disk,
 				grub_disk_from_native_sector (disk, sector),
@@ -1228,7 +1228,7 @@ luks_script_get (grub_size_t *sz)
 	ptr = grub_stpcpy (ptr, "luks_mount ");
 	ptr = grub_stpcpy (ptr, i->uuid);
 	*ptr++ = ' ';
-	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
+	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
 	while (*ptr)
 	  ptr++;
 	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 4ec875821..0175ce4c4 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
     }
   newdev->cipher = cipher;
   newdev->secondary_cipher = secondary_cipher;
-  newdev->offset = 0;
+  newdev->offset_sectors = 0;
   newdev->source_disk = NULL;
   newdev->benbi_log = 0;
   if (grub_le_to_cpu16 (header.alg) == 0x16)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 429db4ad8..aa9877b68 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
   if (!newdev)
       return NULL;
-  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
+  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = 9;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
+  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 3173a098d..26fb14a12 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -605,11 +605,11 @@ luks2_recover_key (grub_disk_t disk,
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
 
       /* Set up disk according to keyslot's segment. */
-      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
+      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
+	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
 
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 21dc69501..258b777bf 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -66,7 +66,12 @@ struct grub_cryptodisk
   struct grub_cryptodisk **prev;
 
   char *source;
-  grub_disk_addr_t offset;
+
+  /*
+   * The number of sectors the start of the encrypted data is offset into the
+   * underlying disk, where sectors are the size noted by log_sector_size.
+   */
+  grub_disk_addr_t offset_sectors;
   /* Total number of encrypted sectors of size (1<<log_sector_size) */
   grub_disk_addr_t total_sectors;
   grub_disk_t source_disk;
-- 
2.27.0



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

* [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
  2020-11-07  4:44         ` [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
  2020-11-07  4:44         ` [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:39           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal Glenn Washburn
                           ` (16 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This makes it more obvious to the reader that the disk referred to is the
source disk, as opposed to say the disk holding the cryptodisk.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 26fb14a12..d963255d4 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -415,7 +415,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
 
 static grub_err_t
 luks2_decrypt_key (grub_uint8_t *out_key,
-		   grub_disk_t disk, grub_cryptodisk_t crypt,
+		   grub_disk_t source, grub_cryptodisk_t crypt,
 		   grub_luks2_keyslot_t *k,
 		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
 {
@@ -491,7 +491,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
     }
 
   grub_errno = GRUB_ERR_NONE;
-  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
+  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
   if (ret)
     {
       grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
@@ -530,7 +530,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 }
 
 static grub_err_t
-luks2_recover_key (grub_disk_t disk,
+luks2_recover_key (grub_disk_t source,
 		   grub_cryptodisk_t crypt)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
@@ -545,7 +545,7 @@ luks2_recover_key (grub_disk_t disk,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  ret = luks2_read_header (disk, &header);
+  ret = luks2_read_header (source, &header);
   if (ret)
     return ret;
 
@@ -554,7 +554,7 @@ luks2_recover_key (grub_disk_t disk,
       return GRUB_ERR_OUT_OF_MEMORY;
 
   /* Read the JSON area. */
-  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
+  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
 			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
   if (ret)
       goto err;
@@ -571,10 +571,10 @@ luks2_recover_key (grub_disk_t disk,
     }
 
   /* Get the passphrase from the user. */
-  if (disk->partition)
-    part = grub_partition_get_name (disk->partition);
-  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
-		disk->partition ? "," : "", part ? : "",
+  if (source->partition)
+    part = grub_partition_get_name (source->partition);
+  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+		source->partition ? "," : "", part ? : "",
 		crypt->uuid);
   if (!grub_password_get (passphrase, MAX_PASSPHRASE))
     {
@@ -609,11 +609,11 @@ luks2_recover_key (grub_disk_t disk,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
+	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
       else
 	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
 
-      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
+      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-- 
2.27.0



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

* [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (2 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:42           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot Glenn Washburn
                           ` (15 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 include/grub/types.h | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/grub/types.h b/include/grub/types.h
index 035a4b528..495c86bb1 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -72,6 +72,14 @@
 # endif
 #endif
 
+#ifndef __CHAR_BIT__
+#error __CHAR_BIT__ is not defined
+#elif __CHAR_BIT__ != 8
+#error __CHAR_BIT__ is not equal 8
+#else
+#define GRUB_CHAR_BIT __CHAR_BIT__
+#endif
+
 /* Define various wide integers.  */
 typedef signed char		grub_int8_t;
 typedef short			grub_int16_t;
@@ -317,6 +325,4 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
   dd->d = val;
 }
 
-#define GRUB_CHAR_BIT 8
-
 #endif /* ! GRUB_TYPES_HEADER */
-- 
2.27.0



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

* [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (3 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:43           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx " Glenn Washburn
                           ` (14 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

The loop variable j should be used to index the digests and segments json
array, instead of the variable i, which is the keyslot index.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d963255d4..be42deb14 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -275,10 +275,10 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
   for (j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&digest, &digests, i) ||
+      if (grub_json_getchild (&digest, &digests, j) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
 
       if ((d->keyslots & (1 << idx)))
 	break;
@@ -292,11 +292,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
   for (j = 0; j < size; j++)
     {
-      if (grub_json_getchild (&segment, &segments, i) ||
+      if (grub_json_getchild (&segment, &segments, j) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
 
       if ((d->segments & (1 << idx)))
 	break;
-- 
2.27.0



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

* [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (4 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:43           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 07/15] luks2: Rename index variable j to i Glenn Washburn
                           ` (13 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Variables named i are usually looping variables, so rename to keyslot_idx to
allow for easier reading of luks2_get_keyslot.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index be42deb14..2830f83cf 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -255,7 +255,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t i)
+		   const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t j, size;
@@ -263,11 +263,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
-      grub_json_getchild (&keyslot, &keyslots, i) ||
+      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
       grub_json_getuint64 (&idx, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, i);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -284,7 +284,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (j == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
-- 
2.27.0



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

* [PATCH v4 07/15] luks2: Rename index variable j to i.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (5 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx " Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:44           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key Glenn Washburn
                           ` (12 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Looping variable j was named such because the variable name i was taken.
Since i has been renamed in the previous patch, we can rename j to i.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2830f83cf..d96764a02 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -258,7 +258,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 		   const grub_json_t *root, grub_size_t keyslot_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
-  grub_size_t j, size;
+  grub_size_t i, size;
   grub_uint64_t idx;
 
   /* Get nth keyslot */
@@ -273,35 +273,35 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   if (grub_json_getvalue (&digests, root, "digests") ||
       grub_json_getsize (&size, &digests))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
-  for (j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&digest, &digests, j) ||
+      if (grub_json_getchild (&digest, &digests, i) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << idx)))
 	break;
     }
-  if (j == size)
+  if (i == size)
       return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (j = 0; j < size; j++)
+  for (i = 0; i < size; i++)
     {
-      if (grub_json_getchild (&segment, &segments, j) ||
+      if (grub_json_getchild (&segment, &segments, i) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << idx)))
 	break;
     }
-  if (j == size)
+  if (i == size)
     return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
 
   return GRUB_ERR_NONE;
-- 
2.27.0



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

* [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (6 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 07/15] luks2: Rename index variable j to i Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:48           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot Glenn Washburn
                           ` (11 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Introduce new variables keyslot_key, digest_key, and segment_key which
represent the integer key of the item in the respective associative array
when looping over the array items. This replaces using a generically
named variable named "idx" used for all three values.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d96764a02..1a4034f28 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -259,12 +259,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t idx;
+  grub_uint64_t keyslot_key, digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
@@ -276,11 +276,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << keyslot_key)))
 	break;
     }
   if (i == size)
@@ -293,12 +294,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&segment, &segments, i) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << segment_key)))
 	break;
     }
   if (i == size)
-- 
2.27.0



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

* [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (7 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:52           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
                           ` (10 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Error messages now distinguish between indexes and keys.  The former
include "index" in the error string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 1a4034f28..9b171bf9d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -267,7 +267,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -279,13 +279,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << keyslot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -297,13 +297,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << segment_key)))
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", digest_key);
 
   return GRUB_ERR_NONE;
 }
-- 
2.27.0



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

* [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (8 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:55           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                           ` (9 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the keyslot key value in the keyslot json array rather than the index of
the keyslot in the json array. This is less confusing for the end user. For
example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
using the password for slot 4 to unlock the device, the messages using the
index of the keyslot will mention keyslot 1 (its a zero-based index).
Furthermore, with this change the keyslot number will align with the number
used to reference the keyslot when using the --key-slot argument to
cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 9b171bf9d..ca830d73b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  grub_uint64_t slot_key;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
 
 struct grub_luks2_segment
 {
+  grub_uint64_t slot_key;
   grub_uint64_t offset;
   const char	*size;
   const char	*encryption;
@@ -112,6 +114,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
 
 struct grub_luks2_digest
 {
+  grub_uint64_t slot_key;
   /* Both keyslots and segments are interpreted as bitfields here */
   grub_uint64_t	keyslots;
   grub_uint64_t	segments;
@@ -259,12 +262,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t keyslot_key, digest_key, segment_key;
+  grub_uint64_t digest_key, segment_key;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
@@ -281,11 +284,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << keyslot_key)))
+      d->slot_key = digest_key;
+      if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -299,6 +303,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
           luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
+      s->slot_key = segment_key;
       if ((d->segments & (1 << segment_key)))
 	break;
     }
@@ -599,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -618,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -635,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (9 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15  9:59           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
                           ` (8 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
bits allocated for type. Also add GRUB_TYPE_U_MAX/MIN(type) macros to get
the max/min values for an unsigned number with size of type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 13 +++++++------
 include/grub/types.h        |  5 +++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 473c93976..31b73c535 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  iv[1] = grub_cpu_to_le32 (sector >> 32);
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
+					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 495c86bb1..b57acc3b1 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -72,6 +72,8 @@
 # endif
 #endif
 
+#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
+
 #ifndef __CHAR_BIT__
 #error __CHAR_BIT__ is not defined
 #elif __CHAR_BIT__ != 8
@@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+#define GRUB_TYPE_U_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BITS (type) - 1)) - 1)) + 1)
+#define GRUB_TYPE_U_MIN(type) 0ULL
+
 typedef grub_uint64_t grub_properly_aligned_t;
 
 #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
-- 
2.27.0



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

* [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (10 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15 10:00           ` Patrick Steinhardt
  2020-11-17 14:06           ` Daniel Kiper
  2020-11-07  4:44         ` [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                           ` (7 subsequent siblings)
  19 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

The total_length field is named confusingly because length usually refers to
bytes, whereas in this case its really the total number of sectors on the
device. Also counter-intuitively, grub_disk_get_size returns the total
number of device native sectors. We need to convert the sectors from the
size of the underlying device to the cryptodisk sector size. And
segment.size is in bytes which need to be converted to cryptodisk sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index ca830d73b..355bb4aec 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
+			       - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (11 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15 10:07           ` Patrick Steinhardt
  2020-11-07  4:44         ` [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
                           ` (6 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 55 ++++++++++++++++++++++---------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 49 insertions(+), 26 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 31b73c535..61f8e57f4 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,12 +238,12 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
 			/ sizeof (grub_uint32_t));
-      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
+      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4] __attribute__((aligned (sizeof (grub_uint64_t))));
 
       if (dev->rekey)
 	{
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,15 +282,25 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
+	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+	  /* The IV is the 64 bit byte offset of the sector. */
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
-					       - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+					       - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -312,10 +323,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -323,10 +334,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -338,7 +349,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -369,11 +380,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -382,10 +393,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -400,9 +411,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -767,7 +778,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -808,7 +819,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index aa9877b68..84c3fa73a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  GRUB_LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 355bb4aec..4a4a0dec4 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      GRUB_LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 258b777bf..ee30e4537 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -145,7 +151,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (12 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15 10:13           ` Patrick Steinhardt
  2020-11-17 14:26           ` Daniel Kiper
  2020-11-07  4:44         ` [PATCH v4 15/15] luks2: Error check segment.sector_size Glenn Washburn
                           ` (5 subsequent siblings)
  19 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 70 +++++++++++++++++++++++++++++++++++++++---
 include/grub/misc.h    |  2 ++
 2 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 4a4a0dec4..751b48d6a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
       goto err;
     }
 
+  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+    {
+      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
+      goto err;
+    }
+
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
+      grub_errno = GRUB_ERR_NONE;
       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
       if (ret)
 	goto err;
@@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
-      crypt->log_sector_size = sizeof (unsigned int) * 8
-		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      crypt->log_sector_size = grub_log2ull (segment.sector_size);
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
-			       - crypt->offset_sectors;
+	{
+	  /* Convert source sized number of sectors to cryptodisk sized sectors */
+	  crypt->total_sectors = source->total_sectors >> (crypt->log_sector_size - source->log_sector_size);
+	  if (crypt->total_sectors < crypt->offset_sectors)
+	    {
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" offset"
+				     " is greater than disk size.",
+				      segment.slot_key);
+	      continue;
+	    }
+
+	  crypt->total_sectors -= crypt->offset_sectors;
+	}
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	{
+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	  if (grub_errno == GRUB_ERR_NONE)
+	    ;
+	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
+	    {
+	      /* TODO: Unparsable number-string, try to use the whole disk */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " is not a parsable number.",
+				     segment.slot_key);
+	      continue;
+	    }
+	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
+	    {
+	      /* There was an overflow in parsing segment.size, so disk must
+	       * be very large or the string is incorrect. */
+	      if ((source->total_sectors
+		    >> (crypt->log_sector_size - source->log_sector_size))
+		  > crypt->total_sectors)
+		{
+		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
+				         " size is very large. The end may be"
+				         " inaccessible.",
+				         segment.slot_key);
+		}
+	      else
+		{
+		  /* FIXME: Set total_sectors as in "dynamic" case. */
+		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
+				         " size greater than the source"
+					 " device.",
+				         segment.slot_key);
+		  continue;
+		}
+	    }
+	}
+
+      if (crypt->total_sectors == 0)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has"
+				 " zero sectors, skipping.",
+				 segment.slot_key);
+	  continue;
+	}
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/misc.h b/include/grub/misc.h
index b7ca6dd58..ec25131ba 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -481,5 +481,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
+#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
+                         - __builtin_clzll (n) - 1)
 
 #endif /* ! GRUB_MISC_HEADER */
-- 
2.27.0



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

* [PATCH v4 15/15] luks2: Error check segment.sector_size.
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (13 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-11-07  4:44         ` Glenn Washburn
  2020-11-15 10:42           ` Patrick Steinhardt
  2020-11-17 14:34         ` [PATCH v4 00/15] Cryptodisk fixes for v2.06 redux Daniel Kiper
                           ` (4 subsequent siblings)
  19 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-07  4:44 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 751b48d6a..b628043e0 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -622,6 +622,17 @@ luks2_recover_key (grub_disk_t source,
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
+      /* Sector size should be one of 512, 1024, 2048, or 4096. */
+      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
+            segment.sector_size == 2048 || segment.sector_size == 4096))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
+				 " size %"PRIuGRUB_UINT64_T" is not one of"
+				 " 512, 1024, 2048, or 4096.",
+				 segment.slot_key, segment.sector_size);
+	  continue;
+	}
+
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = grub_log2ull (segment.sector_size);
-- 
2.27.0



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

* Re: [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-11-07  4:44         ` [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
@ 2020-11-15  9:37           ` Patrick Steinhardt
  2020-11-16 16:22             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:37 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:21PM -0600, Glenn Washburn wrote:
> This creates an alignment with grub_disk_t naming of the same field and is
> more intuitive as to how it should be used.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 2 +-
>  grub-core/disk/geli.c       | 2 +-
>  grub-core/disk/luks.c       | 2 +-
>  grub-core/disk/luks2.c      | 4 ++--
>  include/grub/cryptodisk.h   | 3 ++-
>  5 files changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index a3d672f68..3703da221 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -699,7 +699,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
>      }
>  
>    disk->data = dev;
> -  disk->total_sectors = dev->total_length;
> +  disk->total_sectors = dev->total_sectors;
>    disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
>    disk->id = dev->id;
>    dev->ref++;
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index e9d23299a..4ec875821 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>  
>    newdev->modname = "geli";
>  
> -  newdev->total_length = grub_disk_get_size (disk) - 1;
> +  newdev->total_sectors = 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;
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 59702067a..429db4ad8 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = 9;
> -  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 31d7166fc..3173a098d 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -609,9 +609,9 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_length = grub_disk_get_size (disk) - crypt->offset;
> +	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
>        else
> -	crypt->total_length = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
>  
>        ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index e1b21e785..21dc69501 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -67,7 +67,8 @@ struct grub_cryptodisk
>  
>    char *source;
>    grub_disk_addr_t offset;
> -  grub_disk_addr_t total_length;
> +  /* Total number of encrypted sectors of size (1<<log_sector_size) */
> +  grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
>    int ref;
>    grub_crypto_cipher_handle_t cipher;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-11-07  4:44         ` [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
@ 2020-11-15  9:38           ` Patrick Steinhardt
  2020-11-16 16:25             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:38 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:22PM -0600, Glenn Washburn wrote:
> This makes it clear that the offset represents sectors, not bytes, in order
> to improve readability.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 10 +++++-----
>  grub-core/disk/geli.c       |  2 +-
>  grub-core/disk/luks.c       |  4 ++--
>  grub-core/disk/luks2.c      |  4 ++--
>  include/grub/cryptodisk.h   |  7 ++++++-
>  5 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 3703da221..473c93976 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -754,10 +754,10 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    err = grub_disk_read (dev->source_disk,
> -			grub_disk_from_native_sector (disk, sector + dev->offset),
> +			grub_disk_from_native_sector (disk, sector + dev->offset_sectors),
>  			0, size << disk->log_sector_size, buf);
>    if (err)
>      {
> @@ -803,7 +803,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>    grub_dprintf ("cryptodisk",
>  		"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
>  		PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
> -		size, sector, dev->offset);
> +		size, sector, dev->offset_sectors);
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> @@ -815,7 +815,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>  
>    /* Since ->write was called so disk.mod is loaded but be paranoid  */
> -  sector = sector + dev->offset;
> +  sector = sector + dev->offset_sectors;
>    if (grub_disk_write_weak)
>      err = grub_disk_write_weak (dev->source_disk,
>  				grub_disk_from_native_sector (disk, sector),
> @@ -1228,7 +1228,7 @@ luks_script_get (grub_size_t *sz)
>  	ptr = grub_stpcpy (ptr, "luks_mount ");
>  	ptr = grub_stpcpy (ptr, i->uuid);
>  	*ptr++ = ' ';
> -	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset);
> +	grub_snprintf (ptr, 21, "%" PRIuGRUB_UINT64_T " ", i->offset_sectors);
>  	while (*ptr)
>  	  ptr++;
>  	for (iptr = i->cipher->cipher->name; *iptr; iptr++)
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index 4ec875821..0175ce4c4 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -361,7 +361,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>      }
>    newdev->cipher = cipher;
>    newdev->secondary_cipher = secondary_cipher;
> -  newdev->offset = 0;
> +  newdev->offset_sectors = 0;
>    newdev->source_disk = NULL;
>    newdev->benbi_log = 0;
>    if (grub_le_to_cpu16 (header.alg) == 0x16)
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 429db4ad8..aa9877b68 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -122,10 +122,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
>    if (!newdev)
>        return NULL;
> -  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
> +  newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = 9;
> -  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset;
> +  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 3173a098d..26fb14a12 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -605,11 +605,11 @@ luks2_recover_key (grub_disk_t disk,
>        grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
>  
>        /* Set up disk according to keyslot's segment. */
> -      crypt->offset = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> +      crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset;
> +	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
>  
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 21dc69501..258b777bf 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -66,7 +66,12 @@ struct grub_cryptodisk
>    struct grub_cryptodisk **prev;
>  
>    char *source;
> -  grub_disk_addr_t offset;
> +
> +  /*
> +   * The number of sectors the start of the encrypted data is offset into the
> +   * underlying disk, where sectors are the size noted by log_sector_size.
> +   */
> +  grub_disk_addr_t offset_sectors;
>    /* Total number of encrypted sectors of size (1<<log_sector_size) */
>    grub_disk_addr_t total_sectors;
>    grub_disk_t source_disk;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-11-07  4:44         ` [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
@ 2020-11-15  9:39           ` Patrick Steinhardt
  2020-11-16 16:27             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:39 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:23PM -0600, Glenn Washburn wrote:
> This makes it more obvious to the reader that the disk referred to is the
> source disk, as opposed to say the disk holding the cryptodisk.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 26fb14a12..d963255d4 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -415,7 +415,7 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
>  
>  static grub_err_t
>  luks2_decrypt_key (grub_uint8_t *out_key,
> -		   grub_disk_t disk, grub_cryptodisk_t crypt,
> +		   grub_disk_t source, grub_cryptodisk_t crypt,
>  		   grub_luks2_keyslot_t *k,
>  		   const grub_uint8_t *passphrase, grub_size_t passphraselen)
>  {
> @@ -491,7 +491,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>      }
>  
>    grub_errno = GRUB_ERR_NONE;
> -  ret = grub_disk_read (disk, 0, k->area.offset, k->area.size, split_key);
> +  ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key);
>    if (ret)
>      {
>        grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg);
> @@ -530,7 +530,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>  }
>  
>  static grub_err_t
> -luks2_recover_key (grub_disk_t disk,
> +luks2_recover_key (grub_disk_t source,
>  		   grub_cryptodisk_t crypt)
>  {
>    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
> @@ -545,7 +545,7 @@ luks2_recover_key (grub_disk_t disk,
>    grub_json_t *json = NULL, keyslots;
>    grub_err_t ret;
>  
> -  ret = luks2_read_header (disk, &header);
> +  ret = luks2_read_header (source, &header);
>    if (ret)
>      return ret;
>  
> @@ -554,7 +554,7 @@ luks2_recover_key (grub_disk_t disk,
>        return GRUB_ERR_OUT_OF_MEMORY;
>  
>    /* Read the JSON area. */
> -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
> +  ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header),
>  			grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header);
>    if (ret)
>        goto err;
> @@ -571,10 +571,10 @@ luks2_recover_key (grub_disk_t disk,
>      }
>  
>    /* Get the passphrase from the user. */
> -  if (disk->partition)
> -    part = grub_partition_get_name (disk->partition);
> -  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), disk->name,
> -		disk->partition ? "," : "", part ? : "",
> +  if (source->partition)
> +    part = grub_partition_get_name (source->partition);
> +  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
> +		source->partition ? "," : "", part ? : "",
>  		crypt->uuid);
>    if (!grub_password_get (passphrase, MAX_PASSPHRASE))
>      {
> @@ -609,11 +609,11 @@ luks2_recover_key (grub_disk_t disk,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = grub_disk_get_size (disk) - crypt->offset_sectors;
> +	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
>        else
>  	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
>  
> -      ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot,
> +      ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal.
  2020-11-07  4:44         ` [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal Glenn Washburn
@ 2020-11-15  9:42           ` Patrick Steinhardt
  2020-11-16 16:31             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:42 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:24PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  include/grub/types.h | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 035a4b528..495c86bb1 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -72,6 +72,14 @@
>  # endif
>  #endif
>  
> +#ifndef __CHAR_BIT__
> +#error __CHAR_BIT__ is not defined
> +#elif __CHAR_BIT__ != 8
> +#error __CHAR_BIT__ is not equal 8
> +#else
> +#define GRUB_CHAR_BIT __CHAR_BIT__
> +#endif
> +

Nested defines typically use spaces:

#ifndef __CHAR_BIT__
# error __CHAR_BIT__ is not defined
#elif __CHAR_BIT__ != 8
# error __CHAR_BIT__ is not equal 8
#else
# define GRUB_CHAR_BIT __CHAR_BIT__
#endif

Patrick

>  /* Define various wide integers.  */
>  typedef signed char		grub_int8_t;
>  typedef short			grub_int16_t;
> @@ -317,6 +325,4 @@ static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)
>    dd->d = val;
>  }
>  
> -#define GRUB_CHAR_BIT 8
> -
>  #endif /* ! GRUB_TYPES_HEADER */
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot.
  2020-11-07  4:44         ` [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot Glenn Washburn
@ 2020-11-15  9:43           ` Patrick Steinhardt
  2020-11-16 16:35             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:43 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:25PM -0600, Glenn Washburn wrote:
> The loop variable j should be used to index the digests and segments json
> array, instead of the variable i, which is the keyslot index.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index d963255d4..be42deb14 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -275,10 +275,10 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
>    for (j = 0; j < size; j++)
>      {
> -      if (grub_json_getchild (&digest, &digests, i) ||
> +      if (grub_json_getchild (&digest, &digests, j) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
>  
>        if ((d->keyslots & (1 << idx)))
>  	break;
> @@ -292,11 +292,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
>    for (j = 0; j < size; j++)
>      {
> -      if (grub_json_getchild (&segment, &segments, i) ||
> +      if (grub_json_getchild (&segment, &segments, j) ||
>  	  grub_json_getuint64 (&idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
>  
>        if ((d->segments & (1 << idx)))
>  	break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
  2020-11-07  4:44         ` [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx " Glenn Washburn
@ 2020-11-15  9:43           ` Patrick Steinhardt
  2020-11-16 16:37             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:43 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:26PM -0600, Glenn Washburn wrote:
> Variables named i are usually looping variables, so rename to keyslot_idx to
> allow for easier reading of luks2_get_keyslot.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index be42deb14..2830f83cf 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -255,7 +255,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>  
>  static grub_err_t
>  luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
> -		   const grub_json_t *root, grub_size_t i)
> +		   const grub_json_t *root, grub_size_t keyslot_idx)
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t j, size;
> @@ -263,11 +263,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> -      grub_json_getchild (&keyslot, &keyslots, i) ||
> +      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
>        grub_json_getuint64 (&idx, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, i);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
>  
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
> @@ -284,7 +284,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (j == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 07/15] luks2: Rename index variable j to i.
  2020-11-07  4:44         ` [PATCH v4 07/15] luks2: Rename index variable j to i Glenn Washburn
@ 2020-11-15  9:44           ` Patrick Steinhardt
  2020-11-16 16:38             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:44 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:27PM -0600, Glenn Washburn wrote:
> Looping variable j was named such because the variable name i was taken.
> Since i has been renamed in the previous patch, we can rename j to i.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 2830f83cf..d96764a02 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -258,7 +258,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  		   const grub_json_t *root, grub_size_t keyslot_idx)
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
> -  grub_size_t j, size;
> +  grub_size_t i, size;
>    grub_uint64_t idx;
>  
>    /* Get nth keyslot */
> @@ -273,35 +273,35 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    if (grub_json_getvalue (&digests, root, "digests") ||
>        grub_json_getsize (&size, &digests))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
> -  for (j = 0; j < size; j++)
> +  for (i = 0; i < size; i++)
>      {
> -      if (grub_json_getchild (&digest, &digests, j) ||
> +      if (grub_json_getchild (&digest, &digests, i) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, j);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>  
>        if ((d->keyslots & (1 << idx)))
>  	break;
>      }
> -  if (j == size)
> +  if (i == size)
>        return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
>        grub_json_getsize (&size, &segments))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
> -  for (j = 0; j < size; j++)
> +  for (i = 0; i < size; i++)
>      {
> -      if (grub_json_getchild (&segment, &segments, j) ||
> +      if (grub_json_getchild (&segment, &segments, i) ||
>  	  grub_json_getuint64 (&idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, j);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>  
>        if ((d->segments & (1 << idx)))
>  	break;
>      }
> -  if (j == size)
> +  if (i == size)
>      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
>  
>    return GRUB_ERR_NONE;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
  2020-11-07  4:44         ` [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key Glenn Washburn
@ 2020-11-15  9:48           ` Patrick Steinhardt
  2020-11-17 13:47             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:48 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:28PM -0600, Glenn Washburn wrote:
> Introduce new variables keyslot_key, digest_key, and segment_key which
> represent the integer key of the item in the respective associative array
> when looping over the array items. This replaces using a generically
> named variable named "idx" used for all three values.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index d96764a02..1a4034f28 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -259,12 +259,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t idx;
> +  grub_uint64_t keyslot_key, digest_key, segment_key;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> +      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -276,11 +276,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&digest, &digests, i) ||
> +	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << idx)))
> +      if ((d->keyslots & (1 << keyslot_key)))

It's a bit confusing that this commit introduces `digest_key`, which
isn't used at all right now. It makes sense considering its being used
in the subsequent commit, but it would've helped if this was pointed out
in the commit message.

Other than that: Reviewed-by: Patrick Steinhardt <ps@pks.im>

Patrick

>  	break;
>      }
>    if (i == size)
> @@ -293,12 +294,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&segment, &segments, i) ||
> -	  grub_json_getuint64 (&idx, &segment, NULL) ||
> +	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->segments & (1 << idx)))
> +      if ((d->segments & (1 << segment_key)))
>  	break;
>      }
>    if (i == size)
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot.
  2020-11-07  4:44         ` [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot Glenn Washburn
@ 2020-11-15  9:52           ` Patrick Steinhardt
  2020-11-17 13:51             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:52 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:29PM -0600, Glenn Washburn wrote:
> Error messages now distinguish between indexes and keys.  The former
> include "index" in the error string, and the later are surrounded in quotes.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 1a4034f28..9b171bf9d 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -267,7 +267,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>        grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
>  
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
> @@ -279,13 +279,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->keyslots & (1 << keyslot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -297,13 +297,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&segment_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->segments & (1 << segment_key)))
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", digest_key);
>  
>    return GRUB_ERR_NONE;
>  }
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-11-07  4:44         ` [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
@ 2020-11-15  9:55           ` Patrick Steinhardt
  2020-11-20  8:40             ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:55 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:30PM -0600, Glenn Washburn wrote:
> Use the keyslot key value in the keyslot json array rather than the index of
> the keyslot in the json array. This is less confusing for the end user. For
> example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
> using the password for slot 4 to unlock the device, the messages using the
> index of the keyslot will mention keyslot 1 (its a zero-based index).
> Furthermore, with this change the keyslot number will align with the number
> used to reference the keyslot when using the --key-slot argument to
> cryptsetup.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 27 ++++++++++++++++-----------
>  1 file changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 9b171bf9d..ca830d73b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
>  
>  struct grub_luks2_keyslot
>  {
> +  grub_uint64_t slot_key;
>    grub_int64_t key_size;
>    grub_int64_t priority;
>    struct
> @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
>  
>  struct grub_luks2_segment
>  {
> +  grub_uint64_t slot_key;
>    grub_uint64_t offset;
>    const char	*size;
>    const char	*encryption;
> @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
>  
>  struct grub_luks2_digest
>  {
> +  grub_uint64_t slot_key;
>    /* Both keyslots and segments are interpreted as bitfields here */
>    grub_uint64_t	keyslots;
>    grub_uint64_t	segments;
> @@ -259,12 +262,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t keyslot_key, digest_key, segment_key;
> +  grub_uint64_t digest_key, segment_key;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -281,11 +284,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>            luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << keyslot_key)))
> +      d->slot_key = digest_key;
> +      if ((d->keyslots & (1 << k->slot_key)))

For my own understanding: why don't you directly parse the digest key
into the structure as you do for the keyslot? That'd also allow us to
get rid of the `digest_key` and `segment_key` variables.

Patrick

>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -299,6 +303,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>            luks2_parse_segment (s, &segment))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>  
> +      s->slot_key = segment_key;
>        if ((d->segments & (1 << segment_key)))
>  	break;
>      }
> @@ -599,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
>  	  continue;
>          }
>  
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -618,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -635,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-11-07  4:44         ` [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-11-15  9:59           ` Patrick Steinhardt
  2020-11-20  8:41             ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15  9:59 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:31PM -0600, Glenn Washburn wrote:
> This should improve readability of code by providing clues as to what the
> value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
> bits allocated for type. Also add GRUB_TYPE_U_MAX/MIN(type) macros to get
> the max/min values for an unsigned number with size of type.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 13 +++++++------
>  include/grub/types.h        |  5 +++++
>  2 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 473c93976..31b73c535 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  iv[1] = grub_cpu_to_le32 (sector >> 32);
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> +					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 495c86bb1..b57acc3b1 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -72,6 +72,8 @@
>  # endif
>  #endif
>  
> +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> +
>  #ifndef __CHAR_BIT__
>  #error __CHAR_BIT__ is not defined
>  #elif __CHAR_BIT__ != 8
> @@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
>  #endif
>  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
>  
> +#define GRUB_TYPE_U_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BITS (type) - 1)) - 1)) + 1)

This macro is quite complicated. Considering this is specific to
unsigned types now, couldn't we just use the following?

#define GRUB_TYPE_U_MAX(type) (~((type)0))

Patrick

> +#define GRUB_TYPE_U_MIN(type) 0ULL
> +
>  typedef grub_uint64_t grub_properly_aligned_t;
>  
>  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-11-07  4:44         ` [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
@ 2020-11-15 10:00           ` Patrick Steinhardt
  2020-11-17 14:06           ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15 10:00 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:32PM -0600, Glenn Washburn wrote:
> The total_length field is named confusingly because length usually refers to
> bytes, whereas in this case its really the total number of sectors on the
> device. Also counter-intuitively, grub_disk_get_size returns the total
> number of device native sectors. We need to convert the sectors from the
> size of the underlying device to the cryptodisk sector size. And
> segment.size is in bytes which need to be converted to cryptodisk sectors.
> 
> Also, removed an empty statement.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index ca830d73b..355bb4aec 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>    grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
>    grub_uint8_t *split_key = NULL;
>    grub_size_t saltlen = sizeof (salt);
> -  char cipher[32], *p;;
> +  char cipher[32], *p;
>    const gcry_md_spec_t *hash;
>    gcry_err_code_t gcry_ret;
>    grub_err_t ret;
> @@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
> +	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> +			       - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-07  4:44         ` [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-11-15 10:07           ` Patrick Steinhardt
  2020-11-20  8:42             ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15 10:07 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:33PM -0600, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
> 
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
> 
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 55 ++++++++++++++++++++++---------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 49 insertions(+), 26 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 31b73c535..61f8e57f4 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,12 +238,12 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>  
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
>  			/ sizeof (grub_uint32_t));
> -      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
> +      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4] __attribute__((aligned (sizeof (grub_uint64_t))));
>  
>        if (dev->rekey)
>  	{
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>  
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,15 +282,25 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
> +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> +	      iv[1] = 0;
> +	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> +	  /* The IV is the 64 bit byte offset of the sector. */
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> -					       - dev->log_sector_size));
> -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> +					       - log_sector_size));
> +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>  				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> @@ -312,10 +323,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_CBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -323,10 +334,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_PCBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -338,7 +349,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (err)
>  	      return err;
>  	    
> -	    for (j = 0; j < (1U << dev->log_sector_size);
> +	    for (j = 0; j < (1U << log_sector_size);
>  		 j += dev->cipher->cipher->blocksize)
>  	      {
>  		grub_crypto_xor (data + i + j, data + i + j, iv,
> @@ -369,11 +380,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (do_encrypt)
>  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    else
>  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    if (err)
>  	      return err;
>  	    lrw_xor (&sec, dev, data + i);
> @@ -382,10 +393,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_ECB:
>  	  if (do_encrypt)
>  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  else
>  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -400,9 +411,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector)
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
>  {
> -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
>  }
>  
>  grub_err_t
> @@ -767,7 +778,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
>  					size << disk->log_sector_size,
> -					sector, 0);
> +					sector, dev->log_sector_size, 0);
>    return grub_crypto_gcry_error (gcry_err);
>  }
>  
> @@ -808,7 +819,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> -					sector, 1);
> +					sector, disk->log_sector_size, 1);
>    if (gcry_err)
>      {
>        grub_free (tmp);
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index aa9877b68..84c3fa73a 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
> -  newdev->log_sector_size = 9;
> +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
>    newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
> @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
>  	  return err;
>  	}
>  
> -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> +					  GRUB_LUKS1_LOG_SECTOR_SIZE);
>        if (gcry_err)
>  	{
>  	  grub_free (split_key);
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 355bb4aec..4a4a0dec4 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>        goto err;
>      }
>  
> -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> +  /*
> +   * The key slots area is always encrypted in 512-byte sectors,
> +   * regardless of encrypted data sector size.
> +   */
> +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> +				      GRUB_LUKS1_LOG_SECTOR_SIZE);
>    if (gcry_ret)
>      {
>        ret = grub_crypto_gcry_error (gcry_ret);
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index 258b777bf..ee30e4537 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -48,6 +48,12 @@ typedef enum
>  
>  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
>  
> +/* LUKS1 specification defines the block size to always be 512 bytes. */
> +#define GRUB_LUKS1_LOG_SECTOR_SIZE 9

Sorry to be nitpicky, but this constant is used for both LUKS1 and
LUKS2. Shouldn't it just be called `GRUB_LUKS_LOG_SECTOR_SIZE`?

Patrick

> +/* By default dm-crypt increments the IV every 512 bytes. */
> +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> +
>  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
>  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
> @@ -145,7 +151,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector);
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size);
>  grub_err_t
>  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
>  			grub_disk_t source);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-07  4:44         ` [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-11-15 10:13           ` Patrick Steinhardt
  2020-11-20  8:44             ` Glenn Washburn
  2020-11-17 14:26           ` Daniel Kiper
  1 sibling, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15 10:13 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

A commit message would help to set the stage for your changes here,
especially so as they're non-trivial.

> ---
>  grub-core/disk/luks2.c | 70 +++++++++++++++++++++++++++++++++++++++---
>  include/grub/misc.h    |  2 ++
>  2 files changed, 67 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 4a4a0dec4..751b48d6a 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>  
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
>        if (ret)
>  	goto err;
> @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> -      crypt->log_sector_size = sizeof (unsigned int) * 8
> -		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      crypt->log_sector_size = grub_log2ull (segment.sector_size);
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	{
> +	  /* Convert source sized number of sectors to cryptodisk sized sectors */
> +	  crypt->total_sectors = source->total_sectors >> (crypt->log_sector_size - source->log_sector_size);
> +	  if (crypt->total_sectors < crypt->offset_sectors)
> +	    {
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" offset"
> +				     " is greater than disk size.",
> +				      segment.slot_key);
> +	      continue;
> +	    }
> +
> +	  crypt->total_sectors -= crypt->offset_sectors;
> +	}
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	{
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;

If any other code previously ran which set `grub_errno`, then it would
still carry the old error value here as `grub_strtoull` doesn't unset it
if no error occurred. We'd thus have to first set `grub_errno =
GRUB_ERR_NONE` before the call to `grub_strtoull`.

Patrick

> +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> +	    {
> +	      /* TODO: Unparsable number-string, try to use the whole disk */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " is not a parsable number.",
> +				     segment.slot_key);
> +	      continue;
> +	    }
> +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /* There was an overflow in parsing segment.size, so disk must
> +	       * be very large or the string is incorrect. */
> +	      if ((source->total_sectors
> +		    >> (crypt->log_sector_size - source->log_sector_size))
> +		  > crypt->total_sectors)
> +		{
> +		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
> +				         " size is very large. The end may be"
> +				         " inaccessible.",
> +				         segment.slot_key);
> +		}
> +	      else
> +		{
> +		  /* FIXME: Set total_sectors as in "dynamic" case. */
> +		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
> +				         " size greater than the source"
> +					 " device.",
> +				         segment.slot_key);
> +		  continue;
> +		}
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has"
> +				 " zero sectors, skipping.",
> +				 segment.slot_key);
> +	  continue;
> +	}
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index b7ca6dd58..ec25131ba 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -481,5 +481,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
>  
>  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
>  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
> +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> +                         - __builtin_clzll (n) - 1)
>  
>  #endif /* ! GRUB_MISC_HEADER */
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 15/15] luks2: Error check segment.sector_size.
  2020-11-07  4:44         ` [PATCH v4 15/15] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-11-15 10:42           ` Patrick Steinhardt
  2020-11-17 14:28             ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-15 10:42 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 06, 2020 at 10:44:35PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 751b48d6a..b628043e0 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -622,6 +622,17 @@ luks2_recover_key (grub_disk_t source,
>  
>        grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>  
> +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
> +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
> +            segment.sector_size == 2048 || segment.sector_size == 4096))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
> +				 " size %"PRIuGRUB_UINT64_T" is not one of"
> +				 " 512, 1024, 2048, or 4096.",
> +				 segment.slot_key, segment.sector_size);
> +	  continue;
> +	}
> +
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = grub_log2ull (segment.sector_size);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors.
  2020-11-15  9:37           ` Patrick Steinhardt
@ 2020-11-16 16:22             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:22 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:37:23AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:21PM -0600, Glenn Washburn wrote:
> > This creates an alignment with grub_disk_t naming of the same field and is
> > more intuitive as to how it should be used.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors.
  2020-11-15  9:38           ` Patrick Steinhardt
@ 2020-11-16 16:25             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:25 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:38:18AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:22PM -0600, Glenn Washburn wrote:
> > This makes it clear that the offset represents sectors, not bytes, in order
> > to improve readability.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c.
  2020-11-15  9:39           ` Patrick Steinhardt
@ 2020-11-16 16:27             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:27 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:39:21AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:23PM -0600, Glenn Washburn wrote:
> > This makes it more obvious to the reader that the disk referred to is the
> > source disk, as opposed to say the disk holding the cryptodisk.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal.
  2020-11-15  9:42           ` Patrick Steinhardt
@ 2020-11-16 16:31             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:31 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:42:39AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:24PM -0600, Glenn Washburn wrote:
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  include/grub/types.h | 10 ++++++++--
> >  1 file changed, 8 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index 035a4b528..495c86bb1 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -72,6 +72,14 @@
> >  # endif
> >  #endif
> >
> > +#ifndef __CHAR_BIT__
> > +#error __CHAR_BIT__ is not defined
> > +#elif __CHAR_BIT__ != 8
> > +#error __CHAR_BIT__ is not equal 8
> > +#else
> > +#define GRUB_CHAR_BIT __CHAR_BIT__
> > +#endif
> > +
>
> Nested defines typically use spaces:

Yeah, good point. Anyway, I will fix it before commiting.

> #ifndef __CHAR_BIT__
> # error __CHAR_BIT__ is not defined
> #elif __CHAR_BIT__ != 8
> # error __CHAR_BIT__ is not equal 8
> #else
> # define GRUB_CHAR_BIT __CHAR_BIT__
> #endif

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot.
  2020-11-15  9:43           ` Patrick Steinhardt
@ 2020-11-16 16:35             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:35 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:43:17AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:25PM -0600, Glenn Washburn wrote:
> > The loop variable j should be used to index the digests and segments json
> > array, instead of the variable i, which is the keyslot index.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx in luks2_get_keyslot.
  2020-11-15  9:43           ` Patrick Steinhardt
@ 2020-11-16 16:37             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:37 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:43:55AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:26PM -0600, Glenn Washburn wrote:
> > Variables named i are usually looping variables, so rename to keyslot_idx to
> > allow for easier reading of luks2_get_keyslot.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 07/15] luks2: Rename index variable j to i.
  2020-11-15  9:44           ` Patrick Steinhardt
@ 2020-11-16 16:38             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-16 16:38 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:44:26AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:27PM -0600, Glenn Washburn wrote:
> > Looping variable j was named such because the variable name i was taken.
> > Since i has been renamed in the previous patch, we can rename j to i.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
  2020-11-15  9:48           ` Patrick Steinhardt
@ 2020-11-17 13:47             ` Daniel Kiper
  2020-11-20  8:39               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 13:47 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:48:37AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:28PM -0600, Glenn Washburn wrote:
> > Introduce new variables keyslot_key, digest_key, and segment_key which
> > represent the integer key of the item in the respective associative array
> > when looping over the array items. This replaces using a generically
> > named variable named "idx" used for all three values.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 11 ++++++-----
> >  1 file changed, 6 insertions(+), 5 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index d96764a02..1a4034f28 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -259,12 +259,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
> >  {
> >    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
> >    grub_size_t i, size;
> > -  grub_uint64_t idx;
> > +  grub_uint64_t keyslot_key, digest_key, segment_key;
> >
> >    /* Get nth keyslot */
> >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > +      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> >        grub_json_getchild (&keyslot, &keyslot, 0) ||
> >        luks2_parse_keyslot (k, &keyslot))
> >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> > @@ -276,11 +276,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
> >    for (i = 0; i < size; i++)
> >      {
> >        if (grub_json_getchild (&digest, &digests, i) ||
> > +	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
> >            grub_json_getchild (&digest, &digest, 0) ||
> >            luks2_parse_digest (d, &digest))
> >  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> >
> > -      if ((d->keyslots & (1 << idx)))
> > +      if ((d->keyslots & (1 << keyslot_key)))
>
> It's a bit confusing that this commit introduces `digest_key`, which
> isn't used at all right now. It makes sense considering its being used
> in the subsequent commit, but it would've helped if this was pointed out
> in the commit message.

Yeah, I think the digest_key change should be dropped from this patch.

Daniel


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

* Re: [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot.
  2020-11-15  9:52           ` Patrick Steinhardt
@ 2020-11-17 13:51             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 13:51 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 10:52:03AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:29PM -0600, Glenn Washburn wrote:
> > Error messages now distinguish between indexes and keys.  The former
> > include "index" in the error string, and the later are surrounded in quotes.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-11-07  4:44         ` [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
  2020-11-15 10:00           ` Patrick Steinhardt
@ 2020-11-17 14:06           ` Daniel Kiper
  2020-11-20  8:41             ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 14:06 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 06, 2020 at 10:44:32PM -0600, Glenn Washburn wrote:
> The total_length field is named confusingly because length usually refers to

total_length? I think by mistake you left original commit message here.
It is confusing right now.

> bytes, whereas in this case its really the total number of sectors on the
> device. Also counter-intuitively, grub_disk_get_size returns the total
> number of device native sectors. We need to convert the sectors from the
> size of the underlying device to the cryptodisk sector size. And
> segment.size is in bytes which need to be converted to cryptodisk sectors.
>
> Also, removed an empty statement.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Otherwise patch LGTM.

Daniel


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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-07  4:44         ` [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
  2020-11-15 10:13           ` Patrick Steinhardt
@ 2020-11-17 14:26           ` Daniel Kiper
  2020-11-20  8:44             ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 14:26 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 70 +++++++++++++++++++++++++++++++++++++++---
>  include/grub/misc.h    |  2 ++
>  2 files changed, 67 insertions(+), 5 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 4a4a0dec4..751b48d6a 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
>        if (ret)
>  	goto err;
> @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
>
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> -      crypt->log_sector_size = sizeof (unsigned int) * 8
> -		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      crypt->log_sector_size = grub_log2ull (segment.sector_size);

This change does not belong to this patch.

>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	{
> +	  /* Convert source sized number of sectors to cryptodisk sized sectors */
> +	  crypt->total_sectors = source->total_sectors >> (crypt->log_sector_size - source->log_sector_size);

If you add the other checks could you also add the following check:
  crypt->log_sector_size >= source->log_sector_size ?

> +	  if (crypt->total_sectors < crypt->offset_sectors)
> +	    {
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" offset"
> +				     " is greater than disk size.",

Please replace "." at the end of the message with "\n" here and below...

> +				      segment.slot_key);
> +	      continue;
> +	    }
> +
> +	  crypt->total_sectors -= crypt->offset_sectors;
> +	}
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	{
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;
> +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> +	    {
> +	      /* TODO: Unparsable number-string, try to use the whole disk */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " is not a parsable number.",
> +				     segment.slot_key);
> +	      continue;
> +	    }
> +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /* There was an overflow in parsing segment.size, so disk must
> +	       * be very large or the string is incorrect. */

Please format this comment properly.

> +	      if ((source->total_sectors
> +		    >> (crypt->log_sector_size - source->log_sector_size))
> +		  > crypt->total_sectors)
> +		{
> +		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
> +				         " size is very large. The end may be"
> +				         " inaccessible.",
> +				         segment.slot_key);
> +		}
> +	      else
> +		{
> +		  /* FIXME: Set total_sectors as in "dynamic" case. */
> +		  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\""
> +				         " size greater than the source"
> +					 " device.",
> +				         segment.slot_key);
> +		  continue;
> +		}
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has"
> +				 " zero sectors, skipping.",
> +				 segment.slot_key);
> +	  continue;
> +	}
>
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index b7ca6dd58..ec25131ba 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -481,5 +481,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
>
>  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
>  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))

Please add empty line here.

> +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> +                         - __builtin_clzll (n) - 1)

This change does not belong to this patch too. Additionally, please
double check that misc.h includes all headers which define
GRUB_TYPE_BITS(), grub_uint64_t and __builtin_clzll().

By the way, may I ask you to stop adding full stop to the end of
email subject?

Daniel


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

* Re: [PATCH v4 15/15] luks2: Error check segment.sector_size.
  2020-11-15 10:42           ` Patrick Steinhardt
@ 2020-11-17 14:28             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 14:28 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Nov 15, 2020 at 11:42:24AM +0100, Patrick Steinhardt wrote:
> On Fri, Nov 06, 2020 at 10:44:35PM -0600, Glenn Washburn wrote:
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>
>
> > ---
> >  grub-core/disk/luks2.c | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 751b48d6a..b628043e0 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -622,6 +622,17 @@ luks2_recover_key (grub_disk_t source,
> >
> >        grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
> >
> > +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
> > +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
> > +            segment.sector_size == 2048 || segment.sector_size == 4096))
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
> > +				 " size %"PRIuGRUB_UINT64_T" is not one of"
> > +				 " 512, 1024, 2048, or 4096.",
> > +				 segment.slot_key, segment.sector_size);

s/\.$/\n/

Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v4 00/15] Cryptodisk fixes for v2.06 redux
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (14 preceding siblings ...)
  2020-11-07  4:44         ` [PATCH v4 15/15] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-11-17 14:34         ` Daniel Kiper
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                           ` (3 subsequent siblings)
  19 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-11-17 14:34 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

Hey,

On Fri, Nov 06, 2020 at 10:44:20PM -0600, Glenn Washburn wrote:
> Here we go again. I have not added RB sigs to any patches since I've had to
> modify them in moving them earlier in the patch set.  This would be the first
> three rename patches. The first two patches of v3 have been reworked into 5
> patches (05-09) which combine to be equivalent. Most of the changes since v3 are
> added error handling around luks2 cryptodisk setup. Also, I addressed an IV
> alignment issue in grub_cryptodisk_endecrypt for the
> GRUB_CRYPTODISK_MODE_IV_PLAIN* case, found by Daniel. I'm not sure it works
> (I can't reproduce the build error) or that its the desired way of doing it.

I will take all the patches which got Patrick's and my RB (probably by
the end of this week). Additionally, I will do test build of this whole
patch series and get back to you when I have results in hand. The other
patches still require some rework but it is going in good direction
right now.

Thanks,

Daniel


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-06 19:08           ` Glenn Washburn
@ 2020-11-19 14:25             ` Daniel Kiper
  2020-11-20  5:18               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-19 14:25 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 06, 2020 at 01:08:28PM -0600, Glenn Washburn wrote:
> On Fri, 30 Oct 2020 21:47:14 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> > > By default, dm-crypt internally uses an IV that corresponds to
> > > 512-byte sectors, even when a larger sector size is specified. What
> > > this means is that when using a larger sector size, the IV is
> > > incremented every sector. However, the amount the IV is incremented
> > > is the number of 512 byte blocks in a sector (ie 8 for 4K sectors).
> > > Confusingly the IV does not corespond to the number of, for
> > > example, 4K sectors. So each 512 byte cipher block in a sector will
> > > be encrypted with the same IV and the IV will be incremented
> > > afterwards by the number of 512 byte cipher blocks in the sector.
> > >
> > > There are some encryption utilities which do it the intuitive way
> > > and have the IV equal to the sector number regardless of sector
> > > size (ie. the fifth sector would have an IV of 4 for each cipher
> > > block). And this is supported by dm-crypt with the iv_large_sectors
> > > option and also cryptsetup as of 2.3.3 with the --iv-large-sectors,
> > > though not with LUKS headers (only with --type plain). However,
> > > support for this has not been included as grub does not support
> > > plain devices right now.
> > >
> > > One gotcha here is that the encrypted split keys are encrypted with
> > > a hard- coded 512-byte sector size. So even if your data is
> > > encrypted with 4K sector sizes, the split key encrypted area must
> > > be decrypted with a block size of 512 (ie the IV increments every
> > > 512 bytes). This made these changes less aestetically pleasing than
> > > desired.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/cryptodisk.c | 52
> > > ++++++++++++++++++++++--------------- grub-core/disk/luks.c       |
> > >  5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> > >  include/grub/cryptodisk.h   |  8 +++++-
> > >  4 files changed, 47 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/grub-core/disk/cryptodisk.c
> > > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396 100644
> > > --- a/grub-core/disk/cryptodisk.c
> > > +++ b/grub-core/disk/cryptodisk.c
> > > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> > >  static gcry_err_code_t
> > >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> > >  			   grub_uint8_t * data, grub_size_t len,
> > > -			   grub_disk_addr_t sector, int do_encrypt)
> > > +			   grub_disk_addr_t sector, grub_size_t
> > > log_sector_size,
> > > +			   int do_encrypt)
> > >  {
> > >    grub_size_t i;
> > >    gcry_err_code_t err;
> > > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, return (do_encrypt ? grub_crypto_ecb_encrypt
> > > (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt
> > > (dev->cipher, data, data, len));
> > >
> > > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > > +  for (i = 0; i < len; i += (1U << log_sector_size))
> > >      {
> > >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> > >  			 + sizeof (grub_uint32_t) - 1)
> > > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, if (!ctx)
> > >  	      return GPG_ERR_OUT_OF_MEMORY;
> > >
> > > -	    tmp = grub_cpu_to_le64 (sector <<
> > > dev->log_sector_size);
> > > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> > >  	    dev->iv_hash->init (ctx);
> > >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > > @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, }
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > > -	  /* FALLTHROUGH */
> > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > +	  /*
> > > +	   * The IV is a 32 or 64 bit value of the dm-crypt native
> > > sector
> > > +	   * number. If using 32 bit IV mode, zero out the most
> > > significant
> > > +	   * 32 bits.
> > > +	   */
> > > +	  {
> > > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> >
> > ./configure --target=arm-linux-gnueabihf --with-platform=coreboot ...
> > make
> >
> > ...and you get this:
> >
> >   disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
> >   disk/cryptodisk.c:292:28: error: cast increases required alignment
> > of target type [-Werror=cast-align] grub_uint64_t *iv64 =
> > (grub_uint64_t *)iv; ^
> >   cc1: all warnings being treated as errors
> >
> > I think every 32-bit build will/may fail. It seems to me that
> >   (grub_uint64_t *)(void *) iv;
> > or
> >   (grub_uint64_t *)(grub_addr_t) iv;
> > should help.
>
> I'm having issues building for arm-linux-gnueabihf, so I can't
> effectively test this.  This code does compile for
> --target=i386 --with-platform=pc, which I believe is 32-bit.
>
> Since I can't test your suggestion, I can't verify that it works.
> However, I suspect it may get rid of the compiler problem, but not
> solve the underlying issue, which is that iv may not be 8-byte aligned.
> My guess is that if the compiler message goes away you could get a
> crash at the next line if iv is not 8-byte aligned.  Can you see if the
> warning disappears if you define iv like this:
>
>   grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
>   __attribute__((aligned(sizeof(grub_uint64_t))));
>
> I'm not sure the best way to handle this the "grub way". Do you see a
> better way to do this?

Below you can find all fixes which are needed to properly build
the GRUB with your patches on all platforms. If you have any
questions drop me a line.

Daniel

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 61f8e57f4..b62835acc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -243,7 +243,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
 			/ sizeof (grub_uint32_t));
-      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4] __attribute__((aligned (sizeof (grub_uint64_t))));
+      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];

       if (dev->rekey)
 	{
@@ -289,9 +289,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	   * 32 bits.
 	   */
 	  {
-	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
-	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+	    grub_uint64_t iv64;
+
+	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
 						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    grub_set_unaligned64 (iv, iv64);
 	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
 	      iv[1] = 0;
 	  }
diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index a464200c6..2057c2e0c 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
 }
 #endif

-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 __clzdi2 (grub_uint64_t val)
 {
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
index 7591980b4..17828b322 100644
--- a/include/grub/compiler-rt.h
+++ b/include/grub/compiler-rt.h
@@ -115,7 +115,7 @@ int
 EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
 #endif

-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
 #endif


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-19 14:25             ` Daniel Kiper
@ 2020-11-20  5:18               ` Glenn Washburn
  2020-11-20 14:17                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  5:18 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Thu, 19 Nov 2020 15:25:33 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 06, 2020 at 01:08:28PM -0600, Glenn Washburn wrote:
> > On Fri, 30 Oct 2020 21:47:14 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> > > > By default, dm-crypt internally uses an IV that corresponds to
> > > > 512-byte sectors, even when a larger sector size is specified.
> > > > What this means is that when using a larger sector size, the IV
> > > > is incremented every sector. However, the amount the IV is
> > > > incremented is the number of 512 byte blocks in a sector (ie 8
> > > > for 4K sectors). Confusingly the IV does not corespond to the
> > > > number of, for example, 4K sectors. So each 512 byte cipher
> > > > block in a sector will be encrypted with the same IV and the IV
> > > > will be incremented afterwards by the number of 512 byte cipher
> > > > blocks in the sector.
> > > >
> > > > There are some encryption utilities which do it the intuitive
> > > > way and have the IV equal to the sector number regardless of
> > > > sector size (ie. the fifth sector would have an IV of 4 for
> > > > each cipher block). And this is supported by dm-crypt with the
> > > > iv_large_sectors option and also cryptsetup as of 2.3.3 with
> > > > the --iv-large-sectors, though not with LUKS headers (only with
> > > > --type plain). However, support for this has not been included
> > > > as grub does not support plain devices right now.
> > > >
> > > > One gotcha here is that the encrypted split keys are encrypted
> > > > with a hard- coded 512-byte sector size. So even if your data is
> > > > encrypted with 4K sector sizes, the split key encrypted area
> > > > must be decrypted with a block size of 512 (ie the IV
> > > > increments every 512 bytes). This made these changes less
> > > > aestetically pleasing than desired.
> > > >
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > ---
> > > >  grub-core/disk/cryptodisk.c | 52
> > > > ++++++++++++++++++++++--------------- grub-core/disk/luks.c
> > > >   | 5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> > > >  include/grub/cryptodisk.h   |  8 +++++-
> > > >  4 files changed, 47 insertions(+), 25 deletions(-)
> > > >
> > > > diff --git a/grub-core/disk/cryptodisk.c
> > > > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396 100644
> > > > --- a/grub-core/disk/cryptodisk.c
> > > > +++ b/grub-core/disk/cryptodisk.c
> > > > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> > > >  static gcry_err_code_t
> > > >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> > > >  			   grub_uint8_t * data, grub_size_t
> > > > len,
> > > > -			   grub_disk_addr_t sector, int
> > > > do_encrypt)
> > > > +			   grub_disk_addr_t sector, grub_size_t
> > > > log_sector_size,
> > > > +			   int do_encrypt)
> > > >  {
> > > >    grub_size_t i;
> > > >    gcry_err_code_t err;
> > > > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > > > grub_cryptodisk *dev, return (do_encrypt ?
> > > > grub_crypto_ecb_encrypt (dev->cipher, data, data, len) :
> > > > grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
> > > >
> > > > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > > > +  for (i = 0; i < len; i += (1U << log_sector_size))
> > > >      {
> > > >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> > > >  			 + sizeof (grub_uint32_t) - 1)
> > > > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > > > grub_cryptodisk *dev, if (!ctx)
> > > >  	      return GPG_ERR_OUT_OF_MEMORY;
> > > >
> > > > -	    tmp = grub_cpu_to_le64 (sector <<
> > > > dev->log_sector_size);
> > > > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> > > >  	    dev->iv_hash->init (ctx);
> > > >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > > > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof
> > > > (tmp)); @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct
> > > > grub_cryptodisk *dev, }
> > > >  	  break;
> > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > > > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > > > -	  /* FALLTHROUGH */
> > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > > +	  /*
> > > > +	   * The IV is a 32 or 64 bit value of the dm-crypt
> > > > native sector
> > > > +	   * number. If using 32 bit IV mode, zero out the most
> > > > significant
> > > > +	   * 32 bits.
> > > > +	   */
> > > > +	  {
> > > > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> > >
> > > ./configure --target=arm-linux-gnueabihf --with-platform=coreboot
> > > ... make
> > >
> > > ...and you get this:
> > >
> > >   disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
> > >   disk/cryptodisk.c:292:28: error: cast increases required
> > > alignment of target type [-Werror=cast-align] grub_uint64_t *iv64
> > > = (grub_uint64_t *)iv; ^
> > >   cc1: all warnings being treated as errors
> > >
> > > I think every 32-bit build will/may fail. It seems to me that
> > >   (grub_uint64_t *)(void *) iv;
> > > or
> > >   (grub_uint64_t *)(grub_addr_t) iv;
> > > should help.
> >
> > I'm having issues building for arm-linux-gnueabihf, so I can't
> > effectively test this.  This code does compile for
> > --target=i386 --with-platform=pc, which I believe is 32-bit.
> >
> > Since I can't test your suggestion, I can't verify that it works.
> > However, I suspect it may get rid of the compiler problem, but not
> > solve the underlying issue, which is that iv may not be 8-byte
> > aligned. My guess is that if the compiler message goes away you
> > could get a crash at the next line if iv is not 8-byte aligned.
> > Can you see if the warning disappears if you define iv like this:
> >
> >   grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> >   __attribute__((aligned(sizeof(grub_uint64_t))));
> >
> > I'm not sure the best way to handle this the "grub way". Do you see
> > a better way to do this?
> 
> Below you can find all fixes which are needed to properly build
> the GRUB with your patches on all platforms. If you have any
> questions drop me a line.
> 
> Daniel

Great, thanks for the help.  I'm confused as to why the changes to
compiler-rt* are needed now.  I assume that they are needed because of
the use of __builtin_clzll.  My v4 changes include a patch that moves
the use of __builtin_clzll in luks2.c into a macro in misc.h, but I
don't think that would have necessitated this change because the only
code that uses the macro is in luks2.c.  So the compiler should see no
difference from current master.  Could it be that mips targets are not
properly building with current master due to the use of __builtin_clzll?
Or am I totally off?

I'll add these in the forth coming patch series.  For now, I'll assume
that I should put the compiler-rt* changes in a separate patch and
merge in the cryptodisk.c changes.

Glenn

> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 61f8e57f4..b62835acc 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -243,7 +243,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk
> *dev, grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
>  			/ sizeof (grub_uint32_t));
> -      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> __attribute__((aligned (sizeof (grub_uint64_t))));
> +      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
> 
>        if (dev->rekey)
>  	{
> @@ -289,9 +289,11 @@ grub_cryptodisk_endecrypt (struct
> grub_cryptodisk *dev,
>  	   * 32 bits.
>  	   */
>  	  {
> -	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
> -	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +	    grub_uint64_t iv64;
> +
> +	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
>  						 -
> GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    grub_set_unaligned64 (iv, iv64);
>  	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
>  	      iv[1] = 0;
>  	  }
> diff --git a/grub-core/kern/compiler-rt.c
> b/grub-core/kern/compiler-rt.c index a464200c6..2057c2e0c 100644
> --- a/grub-core/kern/compiler-rt.c
> +++ b/grub-core/kern/compiler-rt.c
> @@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
>  }
>  #endif
> 
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  __clzdi2 (grub_uint64_t val)
>  {
> diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
> index 7591980b4..17828b322 100644
> --- a/include/grub/compiler-rt.h
> +++ b/include/grub/compiler-rt.h
> @@ -115,7 +115,7 @@ int
>  EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
>  #endif
> 
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
>  #endif


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

* Re: [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
  2020-11-17 13:47             ` Daniel Kiper
@ 2020-11-20  8:39               ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:39 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: Patrick Steinhardt, grub-devel

On Tue, 17 Nov 2020 14:47:39 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Sun, Nov 15, 2020 at 10:48:37AM +0100, Patrick Steinhardt wrote:
> > On Fri, Nov 06, 2020 at 10:44:28PM -0600, Glenn Washburn wrote:
> > > Introduce new variables keyslot_key, digest_key, and segment_key
> > > which represent the integer key of the item in the respective
> > > associative array when looping over the array items. This
> > > replaces using a generically named variable named "idx" used for
> > > all three values.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 11 ++++++-----
> > >  1 file changed, 6 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index d96764a02..1a4034f28 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -259,12 +259,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > > grub_luks2_digest_t *d, grub_luks2_s {
> > >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > > segment; grub_size_t i, size;
> > > -  grub_uint64_t idx;
> > > +  grub_uint64_t keyslot_key, digest_key, segment_key;
> > >
> > >    /* Get nth keyslot */
> > >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> > >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > > +      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> > >        grub_json_getchild (&keyslot, &keyslot, 0) ||
> > >        luks2_parse_keyslot (k, &keyslot))
> > >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > > keyslot %"PRIuGRUB_SIZE, keyslot_idx); @@ -276,11 +276,12 @@
> > > luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t
> > > *d, grub_luks2_s for (i = 0; i < size; i++) {
> > >        if (grub_json_getchild (&digest, &digests, i) ||
> > > +	  grub_json_getuint64 (&digest_key, &digest, NULL) ||
> > >            grub_json_getchild (&digest, &digest, 0) ||
> > >            luks2_parse_digest (d, &digest))
> > >  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not
> > > parse digest %"PRIuGRUB_SIZE, i);
> > >
> > > -      if ((d->keyslots & (1 << idx)))
> > > +      if ((d->keyslots & (1 << keyslot_key)))
> >
> > It's a bit confusing that this commit introduces `digest_key`, which
> > isn't used at all right now. It makes sense considering its being
> > used in the subsequent commit, but it would've helped if this was
> > pointed out in the commit message.
> 
> Yeah, I think the digest_key change should be dropped from this patch.
> 
> Daniel

Ok, I'll add it to the following, 09, patch in this series.

Glenn



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

* Re: [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot.
  2020-11-15  9:55           ` Patrick Steinhardt
@ 2020-11-20  8:40             ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:40 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Sun, 15 Nov 2020 10:55:21 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Fri, Nov 06, 2020 at 10:44:30PM -0600, Glenn Washburn wrote:
> > Use the keyslot key value in the keyslot json array rather than the
> > index of the keyslot in the json array. This is less confusing for
> > the end user. For example, say you have a LUKS2 device with a key
> > in slot 1 and slot 4. When using the password for slot 4 to unlock
> > the device, the messages using the index of the keyslot will
> > mention keyslot 1 (its a zero-based index). Furthermore, with this
> > change the keyslot number will align with the number used to
> > reference the keyslot when using the --key-slot argument to
> > cryptsetup.
> > 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 27 ++++++++++++++++-----------
> >  1 file changed, 16 insertions(+), 11 deletions(-)
> > 
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 9b171bf9d..ca830d73b 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -65,6 +65,7 @@ typedef struct grub_luks2_header
> > grub_luks2_header_t; 
> >  struct grub_luks2_keyslot
> >  {
> > +  grub_uint64_t slot_key;
> >    grub_int64_t key_size;
> >    grub_int64_t priority;
> >    struct
> > @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot
> > grub_luks2_keyslot_t; 
> >  struct grub_luks2_segment
> >  {
> > +  grub_uint64_t slot_key;
> >    grub_uint64_t offset;
> >    const char	*size;
> >    const char	*encryption;
> > @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment
> > grub_luks2_segment_t; 
> >  struct grub_luks2_digest
> >  {
> > +  grub_uint64_t slot_key;
> >    /* Both keyslots and segments are interpreted as bitfields here
> > */ grub_uint64_t	keyslots;
> >    grub_uint64_t	segments;
> > @@ -259,12 +262,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s {
> >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > segment; grub_size_t i, size;
> > -  grub_uint64_t keyslot_key, digest_key, segment_key;
> > +  grub_uint64_t digest_key, segment_key;
> >  
> >    /* Get nth keyslot */
> >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > -      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
> > +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
> >        grub_json_getchild (&keyslot, &keyslot, 0) ||
> >        luks2_parse_keyslot (k, &keyslot))
> >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > keyslot index %"PRIuGRUB_SIZE, keyslot_idx); @@ -281,11 +284,12 @@
> > luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d,
> > grub_luks2_s luks2_parse_digest (d, &digest)) return grub_error
> > (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index
> > %"PRIuGRUB_SIZE, i); 
> > -      if ((d->keyslots & (1 << keyslot_key)))
> > +      d->slot_key = digest_key;
> > +      if ((d->keyslots & (1 << k->slot_key)))
> 
> For my own understanding: why don't you directly parse the digest key
> into the structure as you do for the keyslot? That'd also allow us to
> get rid of the `digest_key` and `segment_key` variables.
> 
> Patrick

Thanks for pointing that out.  I was only thinking about the keyslot
key because that's what was needed in luks2_recover_key.  I'll fix that.

> 
> >  	break;
> >      }
> >    if (i == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key); 
> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> > @@ -299,6 +303,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s luks2_parse_segment (s,
> > &segment)) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not
> > parse segment index %"PRIuGRUB_SIZE, i); 
> > +      s->slot_key = segment_key;
> >        if ((d->segments & (1 << segment_key)))
> >  	break;
> >      }
> > @@ -599,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
> >  
> >        if (keyslot.priority == 0)
> >  	{
> > -	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_SIZE" due to priority\n", i);
> > +	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
> > continue; }
> >  
> > -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n",
> > i);
> > +      grub_dprintf ("luks2", "Trying keyslot
> > %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key); 
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); @@ -618,16 +623,16 @@ luks2_recover_key
> > (grub_disk_t source, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_SIZE" failed: %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_UINT64_T" failed: %s\n",
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> >        ret = luks2_verify_key (&digest, candidate_key,
> > keyslot.key_size); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_SIZE": %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_UINT64_T": %s\n",
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> > @@ -635,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
> >         * TRANSLATORS: It's a cryptographic key slot: one element
> > of an array
> >         * where each element is either empty or holds a key.
> >         */
> > -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> > +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"),
> > keyslot.slot_key); 
> >        candidate_key_len = keyslot.key_size;
> >        break;
> > -- 
> > 2.27.0
> > 


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

* Re: [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
  2020-11-15  9:59           ` Patrick Steinhardt
@ 2020-11-20  8:41             ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:41 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Sun, 15 Nov 2020 10:59:33 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Fri, Nov 06, 2020 at 10:44:31PM -0600, Glenn Washburn wrote:
> > This should improve readability of code by providing clues as to
> > what the value represents. The new macro GRUB_TYPE_BITS(type)
> > returns the number of bits allocated for type. Also add
> > GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> > unsigned number with size of type.
> > 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 13 +++++++------
> >  include/grub/types.h        |  5 +++++
> >  2 files changed, 12 insertions(+), 6 deletions(-)
> > 
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index 473c93976..31b73c535 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, iv[1] = grub_cpu_to_le32 (sector >> 32);
> >  	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > dev->log_sector_size));
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > (iv[1])
> > +					       -
> > dev->log_sector_size)); iv[0] = grub_cpu_to_le32 ((sector <<
> > dev->log_sector_size)
> > -				    & 0xFFFFFFFF);
> > +				    & GRUB_TYPE_U_MAX (iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >  	  {
> >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> > -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS
> > (iv[0]));
> > +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX
> > (iv[0])); }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >  					 dev->cipher->cipher->blocksize);
> >  	  if (err)
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index 495c86bb1..b57acc3b1 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -72,6 +72,8 @@
> >  # endif
> >  #endif
> >  
> > +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> > +
> >  #ifndef __CHAR_BIT__
> >  #error __CHAR_BIT__ is not defined
> >  #elif __CHAR_BIT__ != 8
> > @@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
> >  #endif
> >  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
> >  
> > +#define GRUB_TYPE_U_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BITS
> > (type) - 1)) - 1)) + 1)
> 
> This macro is quite complicated. Considering this is specific to
> unsigned types now, couldn't we just use the following?
> 
> #define GRUB_TYPE_U_MAX(type) (~((type)0))
> 
> Patrick

The way its currently defined works for arbitrary bit lengths.  I
suppose its safe to assume that it would only be needed for bit lengths
of actual types.

And your suggestion won't quite work because the bit-complement
operator promotes its argument to an int (or an unsigned int if it
won't fit in an int). So if type is unsigned short, then ~((unsigned
short)0) -> ~((int)0x0) -> 0xffffffff.

However, I think you've hit on a reasonable idea.  This looks like
it'll do what you were intending:

#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof (type))(~0)))

I'll update with this.

Glenn

> 
> > +#define GRUB_TYPE_U_MIN(type) 0ULL
> > +
> >  typedef grub_uint64_t grub_properly_aligned_t;
> >  
> >  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size)
> > grub_properly_aligned_t name[((size) + sizeof
> > (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
> > -- 2.27.0
> > 


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

* Re: [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
  2020-11-17 14:06           ` Daniel Kiper
@ 2020-11-20  8:41             ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:41 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Tue, 17 Nov 2020 15:06:08 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 06, 2020 at 10:44:32PM -0600, Glenn Washburn wrote:
> > The total_length field is named confusingly because length usually
> > refers to
> 
> total_length? I think by mistake you left original commit message
> here. It is confusing right now.
> 
> > bytes, whereas in this case its really the total number of sectors
> > on the device. Also counter-intuitively, grub_disk_get_size returns
> > the total number of device native sectors. We need to convert the
> > sectors from the size of the underlying device to the cryptodisk
> > sector size. And segment.size is in bytes which need to be
> > converted to cryptodisk sectors.
> >
> > Also, removed an empty statement.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> Otherwise patch LGTM.
> 
> Daniel

Damn, I thought I changed that.  Good catch.

Glenn



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

* Re: [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-15 10:07           ` Patrick Steinhardt
@ 2020-11-20  8:42             ` Glenn Washburn
  2020-11-22 12:30               ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:42 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Sun, 15 Nov 2020 11:07:27 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Fri, Nov 06, 2020 at 10:44:33PM -0600, Glenn Washburn wrote:
> > By default, dm-crypt internally uses an IV that corresponds to
> > 512-byte sectors, even when a larger sector size is specified. What
> > this means is that when using a larger sector size, the IV is
> > incremented every sector. However, the amount the IV is incremented
> > is the number of 512 byte blocks in a sector (ie 8 for 4K sectors).
> > Confusingly the IV does not corespond to the number of, for
> > example, 4K sectors. So each 512 byte cipher block in a sector will
> > be encrypted with the same IV and the IV will be incremented
> > afterwards by the number of 512 byte cipher blocks in the sector.
> > 
> > There are some encryption utilities which do it the intuitive way
> > and have the IV equal to the sector number regardless of sector
> > size (ie. the fifth sector would have an IV of 4 for each cipher
> > block). And this is supported by dm-crypt with the iv_large_sectors
> > option and also cryptsetup as of 2.3.3 with the --iv-large-sectors,
> > though not with LUKS headers (only with --type plain). However,
> > support for this has not been included as grub does not support
> > plain devices right now.
> > 
> > One gotcha here is that the encrypted split keys are encrypted with
> > a hard- coded 512-byte sector size. So even if your data is
> > encrypted with 4K sector sizes, the split key encrypted area must
> > be decrypted with a block size of 512 (ie the IV increments every
> > 512 bytes). This made these changes less aestetically pleasing than
> > desired.
> > 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 55
> > ++++++++++++++++++++++--------------- grub-core/disk/luks.c       |
> >  5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> >  include/grub/cryptodisk.h   |  8 +++++-
> >  4 files changed, 49 insertions(+), 26 deletions(-)
> > 
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index 31b73c535..61f8e57f4 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> >  static gcry_err_code_t
> >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> >  			   grub_uint8_t * data, grub_size_t len,
> > -			   grub_disk_addr_t sector, int do_encrypt)
> > +			   grub_disk_addr_t sector, grub_size_t
> > log_sector_size,
> > +			   int do_encrypt)
> >  {
> >    grub_size_t i;
> >    gcry_err_code_t err;
> > @@ -237,12 +238,12 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, return (do_encrypt ? grub_crypto_ecb_encrypt
> > (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt
> > (dev->cipher, data, data, len)); 
> > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > +  for (i = 0; i < len; i += (1U << log_sector_size))
> >      {
> >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> >  			 + sizeof (grub_uint32_t) - 1)
> >  			/ sizeof (grub_uint32_t));
> > -      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
> > +      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> > __attribute__((aligned (sizeof (grub_uint64_t)))); 
> >        if (dev->rekey)
> >  	{
> > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (!ctx)
> >  	      return GPG_ERR_OUT_OF_MEMORY;
> >  
> > -	    tmp = grub_cpu_to_le64 (sector <<
> > dev->log_sector_size);
> > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> >  	    dev->iv_hash->init (ctx);
> >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > @@ -281,15 +282,25 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > -	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0]));
> > +	  /*
> > +	   * The IV is a 32 or 64 bit value of the dm-crypt native
> > sector
> > +	   * number. If using 32 bit IV mode, zero out the most
> > significant
> > +	   * 32 bits.
> > +	   */
> > +	  {
> > +	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
> > +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> > +						 -
> > GRUB_CRYPTODISK_IV_LOG_SIZE));
> > +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> > +	      iv[1] = 0;
> > +	  }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > +	  /* The IV is the 64 bit byte offset of the sector. */
> >  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > (iv[1])
> > -					       -
> > dev->log_sector_size));
> > -	  iv[0] = grub_cpu_to_le32 ((sector <<
> > dev->log_sector_size)
> > +					       - log_sector_size));
> > +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> >  				    & GRUB_TYPE_U_MAX (iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> > @@ -312,10 +323,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_CBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size), iv);
> > +					   (1U <<
> > log_sector_size), iv); else
> >  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size), iv);
> > +					   (1U <<
> > log_sector_size), iv); if (err)
> >  	    return err;
> >  	  break;
> > @@ -323,10 +334,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_PCBC:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i,
> > data + i,
> > -					    (1U <<
> > dev->log_sector_size), iv);
> > +					    (1U <<
> > log_sector_size), iv); else
> >  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i,
> > data + i,
> > -					    (1U <<
> > dev->log_sector_size), iv);
> > +					    (1U <<
> > log_sector_size), iv); if (err)
> >  	    return err;
> >  	  break;
> > @@ -338,7 +349,7 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (err)
> >  	      return err;
> >  	    
> > -	    for (j = 0; j < (1U << dev->log_sector_size);
> > +	    for (j = 0; j < (1U << log_sector_size);
> >  		 j += dev->cipher->cipher->blocksize)
> >  	      {
> >  		grub_crypto_xor (data + i + j, data + i + j, iv,
> > @@ -369,11 +380,11 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, if (do_encrypt)
> >  	      err = grub_crypto_ecb_encrypt (dev->cipher, data +
> > i, data + i,
> > -					     (1U <<
> > dev->log_sector_size));
> > +					     (1U <<
> > log_sector_size)); else
> >  	      err = grub_crypto_ecb_decrypt (dev->cipher, data +
> > i, data + i,
> > -					     (1U <<
> > dev->log_sector_size));
> > +					     (1U <<
> > log_sector_size)); if (err)
> >  	      return err;
> >  	    lrw_xor (&sec, dev, data + i);
> > @@ -382,10 +393,10 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_ECB:
> >  	  if (do_encrypt)
> >  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size));
> > +					   (1U <<
> > log_sector_size)); else
> >  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
> > data + i,
> > -					   (1U <<
> > dev->log_sector_size));
> > +					   (1U <<
> > log_sector_size)); if (err)
> >  	    return err;
> >  	  break;
> > @@ -400,9 +411,9 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, gcry_err_code_t
> >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> >  			 grub_uint8_t * data, grub_size_t len,
> > -			 grub_disk_addr_t sector)
> > +			 grub_disk_addr_t sector, grub_size_t
> > log_sector_size) {
> > -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> > +  return grub_cryptodisk_endecrypt (dev, data, len, sector,
> > log_sector_size, 0); }
> >  
> >  grub_err_t
> > @@ -767,7 +778,7 @@ grub_cryptodisk_read (grub_disk_t disk,
> > grub_disk_addr_t sector, }
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
> >  					size <<
> > disk->log_sector_size,
> > -					sector, 0);
> > +					sector,
> > dev->log_sector_size, 0); return grub_crypto_gcry_error (gcry_err);
> >  }
> >  
> > @@ -808,7 +819,7 @@ grub_cryptodisk_write (grub_disk_t disk,
> > grub_disk_addr_t sector, 
> >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
> >  					size <<
> > disk->log_sector_size,
> > -					sector, 1);
> > +					sector,
> > disk->log_sector_size, 1); if (gcry_err)
> >      {
> >        grub_free (tmp);
> > diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> > index aa9877b68..84c3fa73a 100644
> > --- a/grub-core/disk/luks.c
> > +++ b/grub-core/disk/luks.c
> > @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char
> > *check_uuid, return NULL;
> >    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
> >    newdev->source_disk = NULL;
> > -  newdev->log_sector_size = 9;
> > +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
> >    newdev->total_sectors = grub_disk_get_size (disk) -
> > newdev->offset_sectors; grub_memcpy (newdev->uuid, uuid, sizeof
> > (uuid)); newdev->modname = "luks";
> > @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
> >  	  return err;
> >  	}
> >  
> > -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > 0);
> > +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > 0,
> > +
> > GRUB_LUKS1_LOG_SECTOR_SIZE); if (gcry_err)
> >  	{
> >  	  grub_free (split_key);
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 355bb4aec..4a4a0dec4 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> >        goto err;
> >      }
> >  
> > -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > k->area.size, 0);
> > +  /*
> > +   * The key slots area is always encrypted in 512-byte sectors,
> > +   * regardless of encrypted data sector size.
> > +   */
> > +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > k->area.size, 0,
> > +				      GRUB_LUKS1_LOG_SECTOR_SIZE);
> >    if (gcry_ret)
> >      {
> >        ret = grub_crypto_gcry_error (gcry_ret);
> > diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> > index 258b777bf..ee30e4537 100644
> > --- a/include/grub/cryptodisk.h
> > +++ b/include/grub/cryptodisk.h
> > @@ -48,6 +48,12 @@ typedef enum
> >  
> >  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
> >  
> > +/* LUKS1 specification defines the block size to always be 512
> > bytes. */ +#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
> 
> Sorry to be nitpicky, but this constant is used for both LUKS1 and
> LUKS2. Shouldn't it just be called `GRUB_LUKS_LOG_SECTOR_SIZE`?
> 
> Patrick

Its named LUKS1 because that macro is meant to represent the log of the
sector size for the encrypted data segment, which is fixed at
512-bytes (as you know LUKS2 is variable).  I think a name suggesting
its only for the encrypted key data would be even longer and more
unwieldy. And I don't think just removing the '1' would be an accurate
name. Do you have other suggestions?

Glenn

> 
> > +/* By default dm-crypt increments the IV every 512 bytes. */
> > +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> > +
> >  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
> >  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
> >  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE
> > - 3) @@ -145,7 +151,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t
> > dev, gcry_err_code_t
> >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> >  			 grub_uint8_t * data, grub_size_t len,
> > -			 grub_disk_addr_t sector);
> > +			 grub_disk_addr_t sector, grub_size_t
> > log_sector_size); grub_err_t
> >  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
> >  			grub_disk_t source);
> > -- 
> > 2.27.0
> > 


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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-15 10:13           ` Patrick Steinhardt
@ 2020-11-20  8:44             ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:44 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Sun, 15 Nov 2020 11:13:04 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> A commit message would help to set the stage for your changes here,
> especially so as they're non-trivial.

That's reasonable.  I'll add some commentary.

> > ---
> >  grub-core/disk/luks2.c | 70
> > +++++++++++++++++++++++++++++++++++++++--- include/grub/misc.h    |
> >  2 ++ 2 files changed, 67 insertions(+), 5 deletions(-)
> > 
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 4a4a0dec4..751b48d6a 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
> >        goto err;
> >      }
> >  
> > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > +    {
> > +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> > +      goto err;
> > +    }
> > +
> >    /* Try all keyslot */
> >    for (i = 0; i < size; i++)
> >      {
> > +      grub_errno = GRUB_ERR_NONE;
> >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > i); if (ret)
> >  	goto err;
> > @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
> >  
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL);
> > -      crypt->log_sector_size = sizeof (unsigned int) * 8
> > -		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1;
> > +      crypt->log_sector_size = grub_log2ull (segment.sector_size);
> >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> > -			       - crypt->offset_sectors;
> > +	{
> > +	  /* Convert source sized number of sectors to cryptodisk
> > sized sectors */
> > +	  crypt->total_sectors = source->total_sectors >>
> > (crypt->log_sector_size - source->log_sector_size);
> > +	  if (crypt->total_sectors < crypt->offset_sectors)
> > +	    {
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" offset"
> > +				     " is greater than disk size.",
> > +				      segment.slot_key);
> > +	      continue;
> > +	    }
> > +
> > +	  crypt->total_sectors -= crypt->offset_sectors;
> > +	}
> >        else
> > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size;
> > +	{
> > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > NULL, 10) >> crypt->log_sector_size;
> > +	  if (grub_errno == GRUB_ERR_NONE)
> > +	    ;
> 
> If any other code previously ran which set `grub_errno`, then it would
> still carry the old error value here as `grub_strtoull` doesn't unset
> it if no error occurred. We'd thus have to first set `grub_errno =
> GRUB_ERR_NONE` before the call to `grub_strtoull`.
> 
> Patrick

I intentionally set "grub_errno = GRUB_ERR_NONE" higher up at the start
of the for block.  I was wanting to not clobber any uncaught errors
coming out of luks2_get_keyslot.  But now that I think about it, the
error codes tested for here could come out of luks2_get_keyslot.  So
I'll reset grub_errno here and check for uncaught errors after
luks2_get_keyslot.

Glenn

> > +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> > +	    {
> > +	      /* TODO: Unparsable number-string, try to use the
> > whole disk */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " is not a parsable number.",
> > +				     segment.slot_key);
> > +	      continue;
> > +	    }
> > +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > +	    {
> > +	      /* There was an overflow in parsing segment.size, so
> > disk must
> > +	       * be very large or the string is incorrect. */
> > +	      if ((source->total_sectors
> > +		    >> (crypt->log_sector_size -
> > source->log_sector_size))
> > +		  > crypt->total_sectors)
> > +		{
> > +		  grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\""
> > +				         " size is very large. The
> > end may be"
> > +				         " inaccessible.",
> > +				         segment.slot_key);
> > +		}
> > +	      else
> > +		{
> > +		  /* FIXME: Set total_sectors as in "dynamic"
> > case. */
> > +		  grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\""
> > +				         " size greater than the
> > source"
> > +					 " device.",
> > +				         segment.slot_key);
> > +		  continue;
> > +		}
> > +	    }
> > +	}
> > +
> > +      if (crypt->total_sectors == 0)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has"
> > +				 " zero sectors, skipping.",
> > +				 segment.slot_key);
> > +	  continue;
> > +	}
> >  
> >        ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); diff --git a/include/grub/misc.h
> > b/include/grub/misc.h index b7ca6dd58..ec25131ba 100644
> > --- a/include/grub/misc.h
> > +++ b/include/grub/misc.h
> > @@ -481,5 +481,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const
> > char *file, 
> >  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
> >  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
> > +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> > +                         - __builtin_clzll (n) - 1)
> >  
> >  #endif /* ! GRUB_MISC_HEADER */
> > -- 
> > 2.27.0
> > 


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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-17 14:26           ` Daniel Kiper
@ 2020-11-20  8:44             ` Glenn Washburn
  2020-11-20 20:24               ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20  8:44 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Tue, 17 Nov 2020 15:26:08 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 70
> > +++++++++++++++++++++++++++++++++++++++--- include/grub/misc.h    |
> >  2 ++ 2 files changed, 67 insertions(+), 5 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 4a4a0dec4..751b48d6a 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
> >        goto err;
> >      }
> >
> > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > +    {
> > +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> > +      goto err;
> > +    }
> > +
> >    /* Try all keyslot */
> >    for (i = 0; i < size; i++)
> >      {
> > +      grub_errno = GRUB_ERR_NONE;
> >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > i); if (ret)
> >  	goto err;
> > @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
> >
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL);
> > -      crypt->log_sector_size = sizeof (unsigned int) * 8
> > -		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1;
> > +      crypt->log_sector_size = grub_log2ull (segment.sector_size);
> 
> This change does not belong to this patch.

I'll put it in a new patch.

> >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> > -			       - crypt->offset_sectors;
> > +	{
> > +	  /* Convert source sized number of sectors to cryptodisk
> > sized sectors */
> > +	  crypt->total_sectors = source->total_sectors >>
> > (crypt->log_sector_size - source->log_sector_size);
> 
> If you add the other checks could you also add the following check:
>   crypt->log_sector_size >= source->log_sector_size ?

Why should this be a constraint? I could add it, but I don't see the
problem when crypt->log_sector_size < source->log_sector_size.

> > +	  if (crypt->total_sectors < crypt->offset_sectors)
> > +	    {
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" offset"
> > +				     " is greater than disk size.",
> 
> Please replace "." at the end of the message with "\n" here and
> below...

Good catch.

> > +				      segment.slot_key);
> > +	      continue;
> > +	    }
> > +
> > +	  crypt->total_sectors -= crypt->offset_sectors;
> > +	}
> >        else
> > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size;
> > +	{
> > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > NULL, 10) >> crypt->log_sector_size;
> > +	  if (grub_errno == GRUB_ERR_NONE)
> > +	    ;
> > +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> > +	    {
> > +	      /* TODO: Unparsable number-string, try to use the
> > whole disk */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " is not a parsable number.",
> > +				     segment.slot_key);
> > +	      continue;
> > +	    }
> > +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > +	    {
> > +	      /* There was an overflow in parsing segment.size, so
> > disk must
> > +	       * be very large or the string is incorrect. */
> 
> Please format this comment properly.

Will do.

> > +	      if ((source->total_sectors
> > +		    >> (crypt->log_sector_size -
> > source->log_sector_size))
> > +		  > crypt->total_sectors)
> > +		{
> > +		  grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\""
> > +				         " size is very large. The
> > end may be"
> > +				         " inaccessible.",
> > +				         segment.slot_key);
> > +		}
> > +	      else
> > +		{
> > +		  /* FIXME: Set total_sectors as in "dynamic"
> > case. */
> > +		  grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\""
> > +				         " size greater than the
> > source"
> > +					 " device.",
> > +				         segment.slot_key);
> > +		  continue;
> > +		}
> > +	    }
> > +	}
> > +
> > +      if (crypt->total_sectors == 0)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has"
> > +				 " zero sectors, skipping.",
> > +				 segment.slot_key);
> > +	  continue;
> > +	}
> >
> >        ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); diff --git a/include/grub/misc.h
> > b/include/grub/misc.h index b7ca6dd58..ec25131ba 100644
> > --- a/include/grub/misc.h
> > +++ b/include/grub/misc.h
> > @@ -481,5 +481,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const
> > char *file,
> >
> >  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
> >  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
> 
> Please add empty line here.

Ok.

> > +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> > +                         - __builtin_clzll (n) - 1)
> 
> This change does not belong to this patch too. Additionally, please
> double check that misc.h includes all headers which define
> GRUB_TYPE_BITS(), grub_uint64_t and __builtin_clzll().

I'll add to a new patch.

> By the way, may I ask you to stop adding full stop to the end of
> email subject?

If I understand correctly, you dislike periods ('.') at the end of the
email subject line.  I can not add them.  What do you dislike about
them there? (extra superfluous character?)

Glenn


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-20  5:18               ` Glenn Washburn
@ 2020-11-20 14:17                 ` Daniel Kiper
  2020-11-20 23:28                   ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-20 14:17 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Nov 19, 2020 at 11:18:34PM -0600, Glenn Washburn wrote:
> On Thu, 19 Nov 2020 15:25:33 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 06, 2020 at 01:08:28PM -0600, Glenn Washburn wrote:
> > > On Fri, 30 Oct 2020 21:47:14 +0100
> > > Daniel Kiper <dkiper@net-space.pl> wrote:
> > >
> > > > On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn wrote:
> > > > > By default, dm-crypt internally uses an IV that corresponds to
> > > > > 512-byte sectors, even when a larger sector size is specified.
> > > > > What this means is that when using a larger sector size, the IV
> > > > > is incremented every sector. However, the amount the IV is
> > > > > incremented is the number of 512 byte blocks in a sector (ie 8
> > > > > for 4K sectors). Confusingly the IV does not corespond to the
> > > > > number of, for example, 4K sectors. So each 512 byte cipher
> > > > > block in a sector will be encrypted with the same IV and the IV
> > > > > will be incremented afterwards by the number of 512 byte cipher
> > > > > blocks in the sector.
> > > > >
> > > > > There are some encryption utilities which do it the intuitive
> > > > > way and have the IV equal to the sector number regardless of
> > > > > sector size (ie. the fifth sector would have an IV of 4 for
> > > > > each cipher block). And this is supported by dm-crypt with the
> > > > > iv_large_sectors option and also cryptsetup as of 2.3.3 with
> > > > > the --iv-large-sectors, though not with LUKS headers (only with
> > > > > --type plain). However, support for this has not been included
> > > > > as grub does not support plain devices right now.
> > > > >
> > > > > One gotcha here is that the encrypted split keys are encrypted
> > > > > with a hard- coded 512-byte sector size. So even if your data is
> > > > > encrypted with 4K sector sizes, the split key encrypted area
> > > > > must be decrypted with a block size of 512 (ie the IV
> > > > > increments every 512 bytes). This made these changes less
> > > > > aestetically pleasing than desired.
> > > > >
> > > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > > ---
> > > > >  grub-core/disk/cryptodisk.c | 52
> > > > > ++++++++++++++++++++++--------------- grub-core/disk/luks.c
> > > > >   | 5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> > > > >  include/grub/cryptodisk.h   |  8 +++++-
> > > > >  4 files changed, 47 insertions(+), 25 deletions(-)
> > > > >
> > > > > diff --git a/grub-core/disk/cryptodisk.c
> > > > > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396 100644
> > > > > --- a/grub-core/disk/cryptodisk.c
> > > > > +++ b/grub-core/disk/cryptodisk.c
> > > > > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> > > > >  static gcry_err_code_t
> > > > >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> > > > >  			   grub_uint8_t * data, grub_size_t
> > > > > len,
> > > > > -			   grub_disk_addr_t sector, int
> > > > > do_encrypt)
> > > > > +			   grub_disk_addr_t sector, grub_size_t
> > > > > log_sector_size,
> > > > > +			   int do_encrypt)
> > > > >  {
> > > > >    grub_size_t i;
> > > > >    gcry_err_code_t err;
> > > > > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > > > > grub_cryptodisk *dev, return (do_encrypt ?
> > > > > grub_crypto_ecb_encrypt (dev->cipher, data, data, len) :
> > > > > grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
> > > > >
> > > > > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > > > > +  for (i = 0; i < len; i += (1U << log_sector_size))
> > > > >      {
> > > > >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> > > > >  			 + sizeof (grub_uint32_t) - 1)
> > > > > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > > > > grub_cryptodisk *dev, if (!ctx)
> > > > >  	      return GPG_ERR_OUT_OF_MEMORY;
> > > > >
> > > > > -	    tmp = grub_cpu_to_le64 (sector <<
> > > > > dev->log_sector_size);
> > > > > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> > > > >  	    dev->iv_hash->init (ctx);
> > > > >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > > > > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof
> > > > > (tmp)); @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt (struct
> > > > > grub_cryptodisk *dev, }
> > > > >  	  break;
> > > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > > > > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > > > > -	  /* FALLTHROUGH */
> > > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > > > +	  /*
> > > > > +	   * The IV is a 32 or 64 bit value of the dm-crypt
> > > > > native sector
> > > > > +	   * number. If using 32 bit IV mode, zero out the most
> > > > > significant
> > > > > +	   * 32 bits.
> > > > > +	   */
> > > > > +	  {
> > > > > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> > > >
> > > > ./configure --target=arm-linux-gnueabihf --with-platform=coreboot
> > > > ... make
> > > >
> > > > ...and you get this:
> > > >
> > > >   disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
> > > >   disk/cryptodisk.c:292:28: error: cast increases required
> > > > alignment of target type [-Werror=cast-align] grub_uint64_t *iv64
> > > > = (grub_uint64_t *)iv; ^
> > > >   cc1: all warnings being treated as errors
> > > >
> > > > I think every 32-bit build will/may fail. It seems to me that
> > > >   (grub_uint64_t *)(void *) iv;
> > > > or
> > > >   (grub_uint64_t *)(grub_addr_t) iv;
> > > > should help.
> > >
> > > I'm having issues building for arm-linux-gnueabihf, so I can't
> > > effectively test this.  This code does compile for
> > > --target=i386 --with-platform=pc, which I believe is 32-bit.
> > >
> > > Since I can't test your suggestion, I can't verify that it works.
> > > However, I suspect it may get rid of the compiler problem, but not
> > > solve the underlying issue, which is that iv may not be 8-byte
> > > aligned. My guess is that if the compiler message goes away you
> > > could get a crash at the next line if iv is not 8-byte aligned.
> > > Can you see if the warning disappears if you define iv like this:
> > >
> > >   grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> > >   __attribute__((aligned(sizeof(grub_uint64_t))));
> > >
> > > I'm not sure the best way to handle this the "grub way". Do you see
> > > a better way to do this?
> >
> > Below you can find all fixes which are needed to properly build
> > the GRUB with your patches on all platforms. If you have any
> > questions drop me a line.
> >
> > Daniel
>
> Great, thanks for the help.  I'm confused as to why the changes to
> compiler-rt* are needed now.  I assume that they are needed because of
> the use of __builtin_clzll.  My v4 changes include a patch that moves
> the use of __builtin_clzll in luks2.c into a macro in misc.h, but I
> don't think that would have necessitated this change because the only
> code that uses the macro is in luks2.c.  So the compiler should see no
> difference from current master.  Could it be that mips targets are not
> properly building with current master due to the use of __builtin_clzll?
> Or am I totally off?

I am not sure why this pop up after your patch series. If I have some
time I will dig into it.

> I'll add these in the forth coming patch series.  For now, I'll assume
> that I should put the compiler-rt* changes in a separate patch and
> merge in the cryptodisk.c changes.

Please provide compiler-rt* changes in a separate patch. Good example is
in commit 9dab2f51e (sparc: Enable __clzsi2() and __clzdi2()). Please
include this fix in new patch series.

Daniel


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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-20  8:44             ` Glenn Washburn
@ 2020-11-20 20:24               ` Daniel Kiper
  2020-11-20 23:58                 ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-11-20 20:24 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 20, 2020 at 02:44:53AM -0600, Glenn Washburn wrote:
> On Tue, 17 Nov 2020 15:26:08 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 70
> > > +++++++++++++++++++++++++++++++++++++++--- include/grub/misc.h    |
> > >  2 ++ 2 files changed, 67 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index 4a4a0dec4..751b48d6a 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
> > >        goto err;
> > >      }
> > >
> > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > +    {
> > > +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> > > +      goto err;
> > > +    }
> > > +
> > >    /* Try all keyslot */
> > >    for (i = 0; i < size; i++)
> > >      {
> > > +      grub_errno = GRUB_ERR_NONE;
> > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > > i); if (ret)
> > >  	goto err;
> > > @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
> > >
> > >        /* Set up disk according to keyslot's segment. */
> > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > segment.sector_size, NULL);
> > > -      crypt->log_sector_size = sizeof (unsigned int) * 8
> > > -		- __builtin_clz ((unsigned int)
> > > segment.sector_size) - 1;
> > > +      crypt->log_sector_size = grub_log2ull (segment.sector_size);
> >
> > This change does not belong to this patch.
>
> I'll put it in a new patch.

Thanks!

> > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > (crypt->log_sector_size - source->log_sector_size))
> > > -			       - crypt->offset_sectors;
> > > +	{
> > > +	  /* Convert source sized number of sectors to cryptodisk
> > > sized sectors */
> > > +	  crypt->total_sectors = source->total_sectors >>
> > > (crypt->log_sector_size - source->log_sector_size);
> >
> > If you add the other checks could you also add the following check:
> >   crypt->log_sector_size >= source->log_sector_size ?
>
> Why should this be a constraint? I could add it, but I don't see the
> problem when crypt->log_sector_size < source->log_sector_size.

Is it possible and supported? If yes OK but then I think the result of
(crypt->log_sector_size - source->log_sector_size) has limited set of
values which do not overflow/underflow crypt->total_sectors.

[...]

> > By the way, may I ask you to stop adding full stop to the end of
> > email subject?
>
> If I understand correctly, you dislike periods ('.') at the end of the

Yep!

> email subject line.  I can not add them.  What do you dislike about
> them there? (extra superfluous character?)

Yeah, extra superfluous character which should not be there.

Daniel


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

* Re: [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-20 14:17                 ` Daniel Kiper
@ 2020-11-20 23:28                   ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20 23:28 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Fri, 20 Nov 2020 15:17:25 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Thu, Nov 19, 2020 at 11:18:34PM -0600, Glenn Washburn wrote:
> > On Thu, 19 Nov 2020 15:25:33 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Fri, Nov 06, 2020 at 01:08:28PM -0600, Glenn Washburn wrote:
> > > > On Fri, 30 Oct 2020 21:47:14 +0100
> > > > Daniel Kiper <dkiper@net-space.pl> wrote:
> > > >
> > > > > On Mon, Oct 19, 2020 at 06:09:54PM -0500, Glenn Washburn
> > > > > wrote:
> > > > > > By default, dm-crypt internally uses an IV that corresponds
> > > > > > to 512-byte sectors, even when a larger sector size is
> > > > > > specified. What this means is that when using a larger
> > > > > > sector size, the IV is incremented every sector. However,
> > > > > > the amount the IV is incremented is the number of 512 byte
> > > > > > blocks in a sector (ie 8 for 4K sectors). Confusingly the
> > > > > > IV does not corespond to the number of, for example, 4K
> > > > > > sectors. So each 512 byte cipher block in a sector will be
> > > > > > encrypted with the same IV and the IV will be incremented
> > > > > > afterwards by the number of 512 byte cipher blocks in the
> > > > > > sector.
> > > > > >
> > > > > > There are some encryption utilities which do it the
> > > > > > intuitive way and have the IV equal to the sector number
> > > > > > regardless of sector size (ie. the fifth sector would have
> > > > > > an IV of 4 for each cipher block). And this is supported by
> > > > > > dm-crypt with the iv_large_sectors option and also
> > > > > > cryptsetup as of 2.3.3 with the --iv-large-sectors, though
> > > > > > not with LUKS headers (only with --type plain). However,
> > > > > > support for this has not been included as grub does not
> > > > > > support plain devices right now.
> > > > > >
> > > > > > One gotcha here is that the encrypted split keys are
> > > > > > encrypted with a hard- coded 512-byte sector size. So even
> > > > > > if your data is encrypted with 4K sector sizes, the split
> > > > > > key encrypted area must be decrypted with a block size of
> > > > > > 512 (ie the IV increments every 512 bytes). This made these
> > > > > > changes less aestetically pleasing than desired.
> > > > > >
> > > > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > > > ---
> > > > > >  grub-core/disk/cryptodisk.c | 52
> > > > > > ++++++++++++++++++++++--------------- grub-core/disk/luks.c
> > > > > >   | 5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> > > > > >  include/grub/cryptodisk.h   |  8 +++++-
> > > > > >  4 files changed, 47 insertions(+), 25 deletions(-)
> > > > > >
> > > > > > diff --git a/grub-core/disk/cryptodisk.c
> > > > > > b/grub-core/disk/cryptodisk.c index a3d672f68..623f0f396
> > > > > > 100644 --- a/grub-core/disk/cryptodisk.c
> > > > > > +++ b/grub-core/disk/cryptodisk.c
> > > > > > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> > > > > >  static gcry_err_code_t
> > > > > >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> > > > > >  			   grub_uint8_t * data, grub_size_t
> > > > > > len,
> > > > > > -			   grub_disk_addr_t sector, int
> > > > > > do_encrypt)
> > > > > > +			   grub_disk_addr_t sector,
> > > > > > grub_size_t log_sector_size,
> > > > > > +			   int do_encrypt)
> > > > > >  {
> > > > > >    grub_size_t i;
> > > > > >    gcry_err_code_t err;
> > > > > > @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct
> > > > > > grub_cryptodisk *dev, return (do_encrypt ?
> > > > > > grub_crypto_ecb_encrypt (dev->cipher, data, data, len) :
> > > > > > grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
> > > > > >
> > > > > > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > > > > > +  for (i = 0; i < len; i += (1U << log_sector_size))
> > > > > >      {
> > > > > >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> > > > > >  			 + sizeof (grub_uint32_t) - 1)
> > > > > > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > > > > > grub_cryptodisk *dev, if (!ctx)
> > > > > >  	      return GPG_ERR_OUT_OF_MEMORY;
> > > > > >
> > > > > > -	    tmp = grub_cpu_to_le64 (sector <<
> > > > > > dev->log_sector_size);
> > > > > > +	    tmp = grub_cpu_to_le64 (sector <<
> > > > > > log_sector_size); dev->iv_hash->init (ctx);
> > > > > >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > > > > > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof
> > > > > > (tmp)); @@ -281,14 +282,23 @@ grub_cryptodisk_endecrypt
> > > > > > (struct grub_cryptodisk *dev, }
> > > > > >  	  break;
> > > > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > > > > > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > > > > > -	  /* FALLTHROUGH */
> > > > > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > > > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > > > > +	  /*
> > > > > > +	   * The IV is a 32 or 64 bit value of the dm-crypt
> > > > > > native sector
> > > > > > +	   * number. If using 32 bit IV mode, zero out the
> > > > > > most significant
> > > > > > +	   * 32 bits.
> > > > > > +	   */
> > > > > > +	  {
> > > > > > +	    grub_uint64_t *iv64 = (grub_uint64_t *)iv;
> > > > >
> > > > > ./configure --target=arm-linux-gnueabihf
> > > > > --with-platform=coreboot ... make
> > > > >
> > > > > ...and you get this:
> > > > >
> > > > >   disk/cryptodisk.c: In function ‘grub_cryptodisk_endecrypt’:
> > > > >   disk/cryptodisk.c:292:28: error: cast increases required
> > > > > alignment of target type [-Werror=cast-align] grub_uint64_t
> > > > > *iv64 = (grub_uint64_t *)iv; ^
> > > > >   cc1: all warnings being treated as errors
> > > > >
> > > > > I think every 32-bit build will/may fail. It seems to me that
> > > > >   (grub_uint64_t *)(void *) iv;
> > > > > or
> > > > >   (grub_uint64_t *)(grub_addr_t) iv;
> > > > > should help.
> > > >
> > > > I'm having issues building for arm-linux-gnueabihf, so I can't
> > > > effectively test this.  This code does compile for
> > > > --target=i386 --with-platform=pc, which I believe is 32-bit.
> > > >
> > > > Since I can't test your suggestion, I can't verify that it
> > > > works. However, I suspect it may get rid of the compiler
> > > > problem, but not solve the underlying issue, which is that iv
> > > > may not be 8-byte aligned. My guess is that if the compiler
> > > > message goes away you could get a crash at the next line if iv
> > > > is not 8-byte aligned. Can you see if the warning disappears if
> > > > you define iv like this:
> > > >
> > > >   grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> > > >   __attribute__((aligned(sizeof(grub_uint64_t))));
> > > >
> > > > I'm not sure the best way to handle this the "grub way". Do you
> > > > see a better way to do this?
> > >
> > > Below you can find all fixes which are needed to properly build
> > > the GRUB with your patches on all platforms. If you have any
> > > questions drop me a line.
> > >
> > > Daniel
> >
> > Great, thanks for the help.  I'm confused as to why the changes to
> > compiler-rt* are needed now.  I assume that they are needed because
> > of the use of __builtin_clzll.  My v4 changes include a patch that
> > moves the use of __builtin_clzll in luks2.c into a macro in misc.h,
> > but I don't think that would have necessitated this change because
> > the only code that uses the macro is in luks2.c.  So the compiler
> > should see no difference from current master.  Could it be that
> > mips targets are not properly building with current master due to
> > the use of __builtin_clzll? Or am I totally off?
> 
> I am not sure why this pop up after your patch series. If I have some
> time I will dig into it.
> 
> > I'll add these in the forth coming patch series.  For now, I'll
> > assume that I should put the compiler-rt* changes in a separate
> > patch and merge in the cryptodisk.c changes.
> 
> Please provide compiler-rt* changes in a separate patch. Good example
> is in commit 9dab2f51e (sparc: Enable __clzsi2() and __clzdi2()).
> Please include this fix in new patch series.
> 
> Daniel

Ok, will do.  I'm unsure how to commit the patch though.  Since you are
the author and I am the committer.  I'm thinking I should have my name
as the commit author, but yours should be in a Signed-off-by sig and I
don't need to add a Signed-off-by sig.  How should I proceed?  I'll
follow the commit message template from 9dab2f51e.  Also, how should I
attribute your contribution in cryptodisk.c?

Glenn


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

* Re: [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk.
  2020-11-20 20:24               ` Daniel Kiper
@ 2020-11-20 23:58                 ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-20 23:58 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Fri, 20 Nov 2020 21:24:10 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 20, 2020 at 02:44:53AM -0600, Glenn Washburn wrote:
> > On Tue, 17 Nov 2020 15:26:08 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Fri, Nov 06, 2020 at 10:44:34PM -0600, Glenn Washburn wrote:
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > ---
> > > >  grub-core/disk/luks2.c | 70
> > > > +++++++++++++++++++++++++++++++++++++++--- include/grub/misc.h
> > > >   | 2 ++ 2 files changed, 67 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > index 4a4a0dec4..751b48d6a 100644
> > > > --- a/grub-core/disk/luks2.c
> > > > +++ b/grub-core/disk/luks2.c
> > > > @@ -600,9 +600,16 @@ luks2_recover_key (grub_disk_t source,
> > > >        goto err;
> > > >      }
> > > >
> > > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > > +    {
> > > > +      ret = grub_error (GRUB_ERR_BUG, "not a luks2 device");
> > > > +      goto err;
> > > > +    }
> > > > +
> > > >    /* Try all keyslot */
> > > >    for (i = 0; i < size; i++)
> > > >      {
> > > > +      grub_errno = GRUB_ERR_NONE;
> > > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment,
> > > > json, i); if (ret)
> > > >  	goto err;
> > > > @@ -617,13 +624,66 @@ luks2_recover_key (grub_disk_t source,
> > > >
> > > >        /* Set up disk according to keyslot's segment. */
> > > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > > segment.sector_size, NULL);
> > > > -      crypt->log_sector_size = sizeof (unsigned int) * 8
> > > > -		- __builtin_clz ((unsigned int)
> > > > segment.sector_size) - 1;
> > > > +      crypt->log_sector_size = grub_log2ull
> > > > (segment.sector_size);
> > >
> > > This change does not belong to this patch.
> >
> > I'll put it in a new patch.
> 
> Thanks!
> 
> > > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > > (crypt->log_sector_size - source->log_sector_size))
> > > > -			       - crypt->offset_sectors;
> > > > +	{
> > > > +	  /* Convert source sized number of sectors to
> > > > cryptodisk sized sectors */
> > > > +	  crypt->total_sectors = source->total_sectors >>
> > > > (crypt->log_sector_size - source->log_sector_size);
> > >
> > > If you add the other checks could you also add the following
> > > check: crypt->log_sector_size >= source->log_sector_size ?
> >
> > Why should this be a constraint? I could add it, but I don't see the
> > problem when crypt->log_sector_size < source->log_sector_size.
> 
> Is it possible and supported? 

Why shouldn't it be possible?  LUKS doesn't care about the underlying
sector size of the disk its on.  What is the underlying sector size for
a LUKS volume in a file on a file system with 2k block size on a disk
with 4k sector sizes?  Its all just a stream of bytes to LUKS.  We use
the cryptodisks sector size to determine how to decrypt it, which is
why it matters for grub.  But the source disk sector size adds no
constraints on LUKS nor the cryptodisk.  We just have to translate
between the two occasionally.  Its certainly supported by the linux
implementation of LUKS.  This is a good candidate to add to my tests.

> If yes OK but then I think the result of
> (crypt->log_sector_size - source->log_sector_size) has limited set of
> values which do not overflow/underflow crypt->total_sectors.

Yes, that is problematic in the context of the bit shifts that are being
done, which do not work as desired when the right operand is negative.
I'm refactoring this patch to remove that constraint.

> [...]
> 
> > > By the way, may I ask you to stop adding full stop to the end of
> > > email subject?
> >
> > If I understand correctly, you dislike periods ('.') at the end of
> > the
> 
> Yep!
>
> > email subject line.  I can not add them.  What do you dislike about
> > them there? (extra superfluous character?)
> 
> Yeah, extra superfluous character which should not be there.
> 
> Daniel

I just got it, its really that there should be no periods at the end of
the first line of the commit message.  I'll take care of that.

Glenn


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

* Re: [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors.
  2020-11-20  8:42             ` Glenn Washburn
@ 2020-11-22 12:30               ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-11-22 12:30 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Nov 20, 2020 at 02:42:35AM -0600, Glenn Washburn wrote:
> On Sun, 15 Nov 2020 11:07:27 +0100
> Patrick Steinhardt <ps@pks.im> wrote:
> 
> > On Fri, Nov 06, 2020 at 10:44:33PM -0600, Glenn Washburn wrote:
> > > By default, dm-crypt internally uses an IV that corresponds to
> > > 512-byte sectors, even when a larger sector size is specified. What
> > > this means is that when using a larger sector size, the IV is
> > > incremented every sector. However, the amount the IV is incremented
> > > is the number of 512 byte blocks in a sector (ie 8 for 4K sectors).
> > > Confusingly the IV does not corespond to the number of, for
> > > example, 4K sectors. So each 512 byte cipher block in a sector will
> > > be encrypted with the same IV and the IV will be incremented
> > > afterwards by the number of 512 byte cipher blocks in the sector.
> > > 
> > > There are some encryption utilities which do it the intuitive way
> > > and have the IV equal to the sector number regardless of sector
> > > size (ie. the fifth sector would have an IV of 4 for each cipher
> > > block). And this is supported by dm-crypt with the iv_large_sectors
> > > option and also cryptsetup as of 2.3.3 with the --iv-large-sectors,
> > > though not with LUKS headers (only with --type plain). However,
> > > support for this has not been included as grub does not support
> > > plain devices right now.
> > > 
> > > One gotcha here is that the encrypted split keys are encrypted with
> > > a hard- coded 512-byte sector size. So even if your data is
> > > encrypted with 4K sector sizes, the split key encrypted area must
> > > be decrypted with a block size of 512 (ie the IV increments every
> > > 512 bytes). This made these changes less aestetically pleasing than
> > > desired.
> > > 
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/cryptodisk.c | 55
> > > ++++++++++++++++++++++--------------- grub-core/disk/luks.c       |
> > >  5 ++-- grub-core/disk/luks2.c      |  7 ++++-
> > >  include/grub/cryptodisk.h   |  8 +++++-
> > >  4 files changed, 49 insertions(+), 26 deletions(-)
> > > 
> > > diff --git a/grub-core/disk/cryptodisk.c
> > > b/grub-core/disk/cryptodisk.c index 31b73c535..61f8e57f4 100644
> > > --- a/grub-core/disk/cryptodisk.c
> > > +++ b/grub-core/disk/cryptodisk.c
> > > @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
> > >  static gcry_err_code_t
> > >  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
> > >  			   grub_uint8_t * data, grub_size_t len,
> > > -			   grub_disk_addr_t sector, int do_encrypt)
> > > +			   grub_disk_addr_t sector, grub_size_t
> > > log_sector_size,
> > > +			   int do_encrypt)
> > >  {
> > >    grub_size_t i;
> > >    gcry_err_code_t err;
> > > @@ -237,12 +238,12 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, return (do_encrypt ? grub_crypto_ecb_encrypt
> > > (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt
> > > (dev->cipher, data, data, len)); 
> > > -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> > > +  for (i = 0; i < len; i += (1U << log_sector_size))
> > >      {
> > >        grub_size_t sz = ((dev->cipher->cipher->blocksize
> > >  			 + sizeof (grub_uint32_t) - 1)
> > >  			/ sizeof (grub_uint32_t));
> > > -      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
> > > +      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]
> > > __attribute__((aligned (sizeof (grub_uint64_t)))); 
> > >        if (dev->rekey)
> > >  	{
> > > @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, if (!ctx)
> > >  	      return GPG_ERR_OUT_OF_MEMORY;
> > >  
> > > -	    tmp = grub_cpu_to_le64 (sector <<
> > > dev->log_sector_size);
> > > +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
> > >  	    dev->iv_hash->init (ctx);
> > >  	    dev->iv_hash->write (ctx, dev->iv_prefix,
> > > dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> > > @@ -281,15 +282,25 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, }
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> > > -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> > > -	  /* FALLTHROUGH */
> > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > > (iv[0]));
> > > +	  /*
> > > +	   * The IV is a 32 or 64 bit value of the dm-crypt native
> > > sector
> > > +	   * number. If using 32 bit IV mode, zero out the most
> > > significant
> > > +	   * 32 bits.
> > > +	   */
> > > +	  {
> > > +	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
> > > +	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> > > +						 -
> > > GRUB_CRYPTODISK_IV_LOG_SIZE));
> > > +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> > > +	      iv[1] = 0;
> > > +	  }
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > > +	  /* The IV is the 64 bit byte offset of the sector. */
> > >  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > > (iv[1])
> > > -					       -
> > > dev->log_sector_size));
> > > -	  iv[0] = grub_cpu_to_le32 ((sector <<
> > > dev->log_sector_size)
> > > +					       - log_sector_size));
> > > +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
> > >  				    & GRUB_TYPE_U_MAX (iv[0]));
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> > > @@ -312,10 +323,10 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_CBC:
> > >  	  if (do_encrypt)
> > >  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i,
> > > data + i,
> > > -					   (1U <<
> > > dev->log_sector_size), iv);
> > > +					   (1U <<
> > > log_sector_size), iv); else
> > >  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i,
> > > data + i,
> > > -					   (1U <<
> > > dev->log_sector_size), iv);
> > > +					   (1U <<
> > > log_sector_size), iv); if (err)
> > >  	    return err;
> > >  	  break;
> > > @@ -323,10 +334,10 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_PCBC:
> > >  	  if (do_encrypt)
> > >  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i,
> > > data + i,
> > > -					    (1U <<
> > > dev->log_sector_size), iv);
> > > +					    (1U <<
> > > log_sector_size), iv); else
> > >  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i,
> > > data + i,
> > > -					    (1U <<
> > > dev->log_sector_size), iv);
> > > +					    (1U <<
> > > log_sector_size), iv); if (err)
> > >  	    return err;
> > >  	  break;
> > > @@ -338,7 +349,7 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, if (err)
> > >  	      return err;
> > >  	    
> > > -	    for (j = 0; j < (1U << dev->log_sector_size);
> > > +	    for (j = 0; j < (1U << log_sector_size);
> > >  		 j += dev->cipher->cipher->blocksize)
> > >  	      {
> > >  		grub_crypto_xor (data + i + j, data + i + j, iv,
> > > @@ -369,11 +380,11 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, if (do_encrypt)
> > >  	      err = grub_crypto_ecb_encrypt (dev->cipher, data +
> > > i, data + i,
> > > -					     (1U <<
> > > dev->log_sector_size));
> > > +					     (1U <<
> > > log_sector_size)); else
> > >  	      err = grub_crypto_ecb_decrypt (dev->cipher, data +
> > > i, data + i,
> > > -					     (1U <<
> > > dev->log_sector_size));
> > > +					     (1U <<
> > > log_sector_size)); if (err)
> > >  	      return err;
> > >  	    lrw_xor (&sec, dev, data + i);
> > > @@ -382,10 +393,10 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_ECB:
> > >  	  if (do_encrypt)
> > >  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
> > > data + i,
> > > -					   (1U <<
> > > dev->log_sector_size));
> > > +					   (1U <<
> > > log_sector_size)); else
> > >  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
> > > data + i,
> > > -					   (1U <<
> > > dev->log_sector_size));
> > > +					   (1U <<
> > > log_sector_size)); if (err)
> > >  	    return err;
> > >  	  break;
> > > @@ -400,9 +411,9 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, gcry_err_code_t
> > >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> > >  			 grub_uint8_t * data, grub_size_t len,
> > > -			 grub_disk_addr_t sector)
> > > +			 grub_disk_addr_t sector, grub_size_t
> > > log_sector_size) {
> > > -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> > > +  return grub_cryptodisk_endecrypt (dev, data, len, sector,
> > > log_sector_size, 0); }
> > >  
> > >  grub_err_t
> > > @@ -767,7 +778,7 @@ grub_cryptodisk_read (grub_disk_t disk,
> > > grub_disk_addr_t sector, }
> > >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
> > >  					size <<
> > > disk->log_sector_size,
> > > -					sector, 0);
> > > +					sector,
> > > dev->log_sector_size, 0); return grub_crypto_gcry_error (gcry_err);
> > >  }
> > >  
> > > @@ -808,7 +819,7 @@ grub_cryptodisk_write (grub_disk_t disk,
> > > grub_disk_addr_t sector, 
> > >    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
> > >  					size <<
> > > disk->log_sector_size,
> > > -					sector, 1);
> > > +					sector,
> > > disk->log_sector_size, 1); if (gcry_err)
> > >      {
> > >        grub_free (tmp);
> > > diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> > > index aa9877b68..84c3fa73a 100644
> > > --- a/grub-core/disk/luks.c
> > > +++ b/grub-core/disk/luks.c
> > > @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char
> > > *check_uuid, return NULL;
> > >    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
> > >    newdev->source_disk = NULL;
> > > -  newdev->log_sector_size = 9;
> > > +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
> > >    newdev->total_sectors = grub_disk_get_size (disk) -
> > > newdev->offset_sectors; grub_memcpy (newdev->uuid, uuid, sizeof
> > > (uuid)); newdev->modname = "luks";
> > > @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
> > >  	  return err;
> > >  	}
> > >  
> > > -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > > 0);
> > > +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length,
> > > 0,
> > > +
> > > GRUB_LUKS1_LOG_SECTOR_SIZE); if (gcry_err)
> > >  	{
> > >  	  grub_free (split_key);
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index 355bb4aec..4a4a0dec4 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> > >        goto err;
> > >      }
> > >  
> > > -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > > k->area.size, 0);
> > > +  /*
> > > +   * The key slots area is always encrypted in 512-byte sectors,
> > > +   * regardless of encrypted data sector size.
> > > +   */
> > > +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key,
> > > k->area.size, 0,
> > > +				      GRUB_LUKS1_LOG_SECTOR_SIZE);
> > >    if (gcry_ret)
> > >      {
> > >        ret = grub_crypto_gcry_error (gcry_ret);
> > > diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> > > index 258b777bf..ee30e4537 100644
> > > --- a/include/grub/cryptodisk.h
> > > +++ b/include/grub/cryptodisk.h
> > > @@ -48,6 +48,12 @@ typedef enum
> > >  
> > >  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
> > >  
> > > +/* LUKS1 specification defines the block size to always be 512
> > > bytes. */ +#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
> > 
> > Sorry to be nitpicky, but this constant is used for both LUKS1 and
> > LUKS2. Shouldn't it just be called `GRUB_LUKS_LOG_SECTOR_SIZE`?
> > 
> > Patrick
> 
> Its named LUKS1 because that macro is meant to represent the log of the
> sector size for the encrypted data segment, which is fixed at
> 512-bytes (as you know LUKS2 is variable).  I think a name suggesting
> its only for the encrypted key data would be even longer and more
> unwieldy. And I don't think just removing the '1' would be an accurate
> name. Do you have other suggestions?
> 
> Glenn

I mean we could split it up into two constants,
`GRUB_LUKS1_LOG_SECTOR_SIZE` and `GRUB_LUKS2_KEYSLOT_LOG_SECTOR_SIZE`.
Not sure if it's worth it, though.

Patrick

> > 
> > > +/* By default dm-crypt increments the IV every 512 bytes. */
> > > +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> > > +
> > >  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
> > >  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
> > >  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE
> > > - 3) @@ -145,7 +151,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t
> > > dev, gcry_err_code_t
> > >  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
> > >  			 grub_uint8_t * data, grub_size_t len,
> > > -			 grub_disk_addr_t sector);
> > > +			 grub_disk_addr_t sector, grub_size_t
> > > log_sector_size); grub_err_t
> > >  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
> > >  			grub_disk_t source);
> > > -- 
> > > 2.27.0
> > > 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* [PATCH v5 00/11] Cryptodisk fixes for v2.06 redux
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (15 preceding siblings ...)
  2020-11-17 14:34         ` [PATCH v4 00/15] Cryptodisk fixes for v2.06 redux Daniel Kiper
@ 2020-11-23  5:23         ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 01/11] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
                             ` (10 more replies)
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                           ` (2 subsequent siblings)
  19 siblings, 11 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This incorporates changes as noted in the v4 thread. This series has been
rebased on the new master from accepted patches from v4. This means that patch
8 from v4 would be patch 1 in this series.  However, I reworked 8-10 from v4
from 3 patches into 2, and I believe simplified the changeset. So v4 patches
8-10 are equivalent to patches 1-2 here.

Also, the v4 patch 14 has been nearly completely reworked to be easier to follow
and more precisely reflect the error handling I wanted.

The changes that created and used grub_log2ull in v4 patch 14 has been pulled
out into two separate patches. And there is a new patch converting spaces to
tabs missed in the original commit of luks2.

Glenn

Glenn Washburn (11):
  luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  luks: Use more intuitive slot key instead of index in user messages.
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt
  luks2: grub_cryptodisk_t->total_sectors is the max number of device
    native sectors
  cryptodisk: Properly handle non-512 byte sized sectors
  luks2: Better error handling when setting up the cryptodisk
  luks2: Error check segment.sector_size
  whitespace: convert 8 spaces to tabs.
  mips: Enable __clzdi2()
  misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
    integers
  luks2: Use grub_log2ull to calculate log_sector_size and improve
    readability

 grub-core/disk/cryptodisk.c  |  64 ++++++++++------
 grub-core/disk/luks.c        |   5 +-
 grub-core/disk/luks2.c       | 144 ++++++++++++++++++++++++++++-------
 grub-core/kern/compiler-rt.c |   2 +-
 include/grub/compiler-rt.h   |   2 +-
 include/grub/cryptodisk.h    |   8 +-
 include/grub/disk.h          |  16 ++++
 include/grub/misc.h          |   3 +
 include/grub/types.h         |   5 ++
 9 files changed, 192 insertions(+), 57 deletions(-)

Range-diff against v4:
 1:  f1d530757 <  -:  --------- luks2: Split idx into three variables: keyslot_key, digest_key, segment_key.
 2:  b90ab8e75 <  -:  --------- luks2: Improve error messages in luks2_get_keyslot.
 -:  --------- >  1:  ec506b668 luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
 3:  51add6875 !  2:  3a9fca36f luks2: Use more intuitive keyslot key instead of index when naming keyslot.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Use more intuitive keyslot key instead of index when naming keyslot.
    +    luks: Use more intuitive slot key instead of index in user messages.
     
    -    Use the keyslot key value in the keyslot json array rather than the index of
    -    the keyslot in the json array. This is less confusing for the end user. For
    -    example, say you have a LUKS2 device with a key in slot 1 and slot 4. When
    -    using the password for slot 4 to unlock the device, the messages using the
    -    index of the keyslot will mention keyslot 1 (its a zero-based index).
    -    Furthermore, with this change the keyslot number will align with the number
    -    used to reference the keyslot when using the --key-slot argument to
    -    cryptsetup.
    +    Use the slot key name in the json array rather than the 0 based index in the
    +    json array for keyslots, segments, and digests. This is less confusing for
    +    the end user. For example, say you have a LUKS2 device with a key in slot 1
    +    and slot 4. When using the password for slot 4 to unlock the device, the
    +    messages using the index of the keyslot will mention keyslot 1 (its a
    +    zero-based index). Furthermore, with this change the keyslot number will
    +    align with the number used to reference the keyslot when using the
    +    --key-slot argument to cryptsetup. Error messages now distinguish between
    +    indexes and slot keys. The former include the string "index" in the error
    +    string, and the later are surrounded in quotes.
     
      ## grub-core/disk/luks2.c ##
    -@@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
    - 
    - struct grub_luks2_keyslot
    - {
    -+  grub_uint64_t slot_key;
    -   grub_int64_t key_size;
    -   grub_int64_t priority;
    -   struct
    -@@ grub-core/disk/luks2.c: typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
    - 
    - struct grub_luks2_segment
    - {
    -+  grub_uint64_t slot_key;
    -   grub_uint64_t offset;
    -   const char	*size;
    -   const char	*encryption;
    -@@ grub-core/disk/luks2.c: typedef struct grub_luks2_segment grub_luks2_segment_t;
    - 
    - struct grub_luks2_digest
    - {
    -+  grub_uint64_t slot_key;
    -   /* Both keyslots and segments are interpreted as bitfields here */
    -   grub_uint64_t	keyslots;
    -   grub_uint64_t	segments;
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - {
    -   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
    -   grub_size_t i, size;
    --  grub_uint64_t keyslot_key, digest_key, segment_key;
    -+  grub_uint64_t digest_key, segment_key;
    - 
    -   /* Get nth keyslot */
    -   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
    -       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
    --      grub_json_getuint64 (&keyslot_key, &keyslot, NULL) ||
    -+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
    +       grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
            grub_json_getchild (&keyslot, &keyslot, 0) ||
            luks2_parse_keyslot (k, &keyslot))
    -     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
    +-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
    ++    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
    + 
    +   /* Get digest that matches the keyslot. */
    +   if (grub_json_getvalue (&digests, root, "digests") ||
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    + 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
    +           grub_json_getchild (&digest, &digest, 0) ||
                luks2_parse_digest (d, &digest))
    - 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
    +-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
    ++	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
      
    --      if ((d->keyslots & (1 << keyslot_key)))
    -+      d->slot_key = digest_key;
    -+      if ((d->keyslots & (1 << k->slot_key)))
    +       if ((d->keyslots & (1 << k->slot_key)))
      	break;
          }
        if (i == size)
    --      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", keyslot_key);
    +-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
     +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
      
        /* Get segment that matches the digest. */
        if (grub_json_getvalue (&segments, root, "segments") ||
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    + 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
    + 	  grub_json_getchild (&segment, &segment, 0) ||
                luks2_parse_segment (s, &segment))
    - 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
    +-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
    ++	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
      
    -+      s->slot_key = segment_key;
    -       if ((d->segments & (1 << segment_key)))
    +       if ((d->segments & (1 << s->slot_key)))
      	break;
          }
    +   if (i == size)
    +-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
    ++    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
    + 
    +   return GRUB_ERR_NONE;
    + }
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
            if (keyslot.priority == 0)
 4:  39e382053 !  3:  f45f5f3dd cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt.
    +    cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
     
         This should improve readability of code by providing clues as to what the
         value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
    @@ include/grub/types.h: typedef grub_int32_t	grub_ssize_t;
      #endif
      # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
      
    -+#define GRUB_TYPE_U_MAX(type) ((2 * ((1ULL << (GRUB_TYPE_BITS (type) - 1)) - 1)) + 1)
    ++#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof (type))(~0)))
     +#define GRUB_TYPE_U_MIN(type) 0ULL
     +
      typedef grub_uint64_t grub_properly_aligned_t;
 5:  7696a000f !  4:  da2b63607 luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: grub_cryptodisk_t->total_length is the max number of device native sectors
    +    luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
     
    -    The total_length field is named confusingly because length usually refers to
    -    bytes, whereas in this case its really the total number of sectors on the
    -    device. Also counter-intuitively, grub_disk_get_size returns the total
    -    number of device native sectors. We need to convert the sectors from the
    -    size of the underlying device to the cryptodisk sector size. And
    -    segment.size is in bytes which need to be converted to cryptodisk sectors.
    +    We need to convert the sectors from the size of the underlying device to the
    +    cryptodisk sector size; segment.size is in bytes which need to be converted
    +    to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
    +    returns the total number of device native sectors.
     
         Also, removed an empty statement.
     
 6:  43437eb13 !  5:  036304262 cryptodisk: Properly handle non-512 byte sized sectors.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    cryptodisk: Properly handle non-512 byte sized sectors.
    +    cryptodisk: Properly handle non-512 byte sized sectors
     
         By default, dm-crypt internally uses an IV that corresponds to 512-byte
         sectors, even when a larger sector size is specified. What this means is
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
          {
            grub_size_t sz = ((dev->cipher->cipher->blocksize
      			 + sizeof (grub_uint32_t) - 1)
    - 			/ sizeof (grub_uint32_t));
    --      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
    -+      grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4] __attribute__((aligned (sizeof (grub_uint64_t))));
    - 
    -       if (dev->rekey)
    - 	{
     @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
      	    if (!ctx)
      	      return GPG_ERR_OUT_OF_MEMORY;
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
     +	   * 32 bits.
     +	   */
     +	  {
    -+	    grub_uint64_t *iv64 = (grub_uint64_t *) iv;
    -+	    *iv64 = grub_cpu_to_le64 (sector << (log_sector_size
    ++	    grub_uint64_t iv64;
    ++
    ++	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
     +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
    ++	    grub_set_unaligned64 (iv, iv64);
     +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
     +	      iv[1] = 0;
     +	  }
 7:  71dadcd07 <  -:  --------- luks2: Better error handling when setting up the cryptodisk.
 -:  --------- >  6:  7bf56c4b3 luks2: Better error handling when setting up the cryptodisk
 8:  cc96baf5a !  7:  b167b014d luks2: Error check segment.sector_size.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Error check segment.sector_size.
    +    luks2: Error check segment.sector_size
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
     +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
     +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
    -+            segment.sector_size == 2048 || segment.sector_size == 4096))
    ++	    segment.sector_size == 2048 || segment.sector_size == 4096))
     +	{
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
     +				 " size %"PRIuGRUB_UINT64_T" is not one of"
    -+				 " 512, 1024, 2048, or 4096.",
    ++				 " 512, 1024, 2048, or 4096\n",
     +				 segment.slot_key, segment.sector_size);
     +	  continue;
     +	}
     +
            /* Set up disk according to keyslot's segment. */
            crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    -       crypt->log_sector_size = grub_log2ull (segment.sector_size);
    +       crypt->log_sector_size = sizeof (unsigned int) * 8
 -:  --------- >  8:  c503ecbb8 whitespace: convert 8 spaces to tabs.
 -:  --------- >  9:  8316e94ce mips: Enable __clzdi2()
 -:  --------- > 10:  37257725c misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
 -:  --------- > 11:  8dd088cad luks2: Use grub_log2ull to calculate log_sector_size and improve readability
-- 
2.27.0



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

* [PATCH v5 01/11] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 02/11] luks: Use more intuitive slot key instead of index in user messages Glenn Washburn
                             ` (9 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows code using these structs to know the named key associated with
these json data structures. In the future we can use these to provide better
error messages to the user.

Get rid of idx variable in luks2_get_keyslot which was overloaded to be used
for both keyslot and segment slot keys.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d96764a02..ab2c31dcd 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  grub_uint64_t slot_key;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
 
 struct grub_luks2_segment
 {
+  grub_uint64_t slot_key;
   grub_uint64_t offset;
   const char	*size;
   const char	*encryption;
@@ -112,6 +114,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
 
 struct grub_luks2_digest
 {
+  grub_uint64_t slot_key;
   /* Both keyslots and segments are interpreted as bitfields here */
   grub_uint64_t	keyslots;
   grub_uint64_t	segments;
@@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t idx;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
@@ -276,11 +278,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
@@ -293,12 +296,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&segment, &segments, i) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << s->slot_key)))
 	break;
     }
   if (i == size)
-- 
2.27.0



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

* [PATCH v5 02/11] luks: Use more intuitive slot key instead of index in user messages.
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 01/11] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 03/11] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                             ` (8 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the slot key name in the json array rather than the 0 based index in the
json array for keyslots, segments, and digests. This is less confusing for
the end user. For example, say you have a LUKS2 device with a key in slot 1
and slot 4. When using the password for slot 4 to unlock the device, the
messages using the index of the keyslot will mention keyslot 1 (its a
zero-based index). Furthermore, with this change the keyslot number will
align with the number used to reference the keyslot when using the
--key-slot argument to cryptsetup. Error messages now distinguish between
indexes and slot keys. The former include the string "index" in the error
string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index ab2c31dcd..c390ea3e6 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -269,7 +269,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -281,13 +281,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -299,13 +299,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->slot_key)))
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
 
   return GRUB_ERR_NONE;
 }
@@ -601,11 +601,11 @@ luks2_recover_key (grub_disk_t source,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -620,16 +620,16 @@ luks2_recover_key (grub_disk_t source,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -637,7 +637,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v5 03/11] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 01/11] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 02/11] luks: Use more intuitive slot key instead of index in user messages Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 04/11] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
                             ` (7 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
bits allocated for type. Also add GRUB_TYPE_U_MAX/MIN(type) macros to get
the max/min values for an unsigned number with size of type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 13 +++++++------
 include/grub/types.h        |  5 +++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 473c93976..31b73c535 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  iv[1] = grub_cpu_to_le32 (sector >> 32);
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
+					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 9cd7e2525..b9c7426fc 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -72,6 +72,8 @@
 # endif
 #endif
 
+#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
+
 #ifndef __CHAR_BIT__
 # error __CHAR_BIT__ is not defined
 #elif __CHAR_BIT__ != 8
@@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof (type))(~0)))
+#define GRUB_TYPE_U_MIN(type) 0ULL
+
 typedef grub_uint64_t grub_properly_aligned_t;
 
 #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
-- 
2.27.0



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

* [PATCH v5 04/11] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (2 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 03/11] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 05/11] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                             ` (6 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

We need to convert the sectors from the size of the underlying device to the
cryptodisk sector size; segment.size is in bytes which need to be converted
to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
returns the total number of device native sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c390ea3e6..e33df9803 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -426,7 +426,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -612,9 +612,10 @@ luks2_recover_key (grub_disk_t source,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
+			       - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v5 05/11] cryptodisk: Properly handle non-512 byte sized sectors
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (3 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 04/11] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 06/11] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
                             ` (5 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 31b73c535..b62835acc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t iv64;
+
+	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    grub_set_unaligned64 (iv, iv64);
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+	  /* The IV is the 64 bit byte offset of the sector. */
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
-					       - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+					       - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index aa9877b68..84c3fa73a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  GRUB_LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index e33df9803..5e3b255b9 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -501,7 +501,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      GRUB_LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 258b777bf..ee30e4537 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -145,7 +151,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v5 06/11] luks2: Better error handling when setting up the cryptodisk
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (4 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 05/11] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 07/11] luks2: Error check segment.sector_size Glenn Washburn
                             ` (4 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

First, check to make sure that source disk has a known size. If not, print
debug message and return error. There are 4 cases where
GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
all those cases processing continues. So this is probably a bit
conservative. However, 3 of the cases seem pathological, and the other,
biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
volume on a cd is a big use case, we'll error until someone complains.

Do some sanity checking on data coming from the luks header. If segment.size
is "dynamic",

Check for errors from grub_strtoull when converting segment size from
string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
returned, then there was an overflow in converting to a 64-bit unsigned
integer. So this could be a very large disk (perhaps large raid array).
In this case, we want to continue to try to use this key so long as the
source disk's size is greater than this segment size. Otherwise, this is
an invalid segment, and continue on to the next key.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 77 ++++++++++++++++++++++++++++++++++++++++--
 include/grub/disk.h    | 16 +++++++++
 2 files changed, 90 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 5e3b255b9..2f2515fb6 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
       goto err;
     }
 
+  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+    {
+      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
+      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
+			     "conservatively returning error\n", source->name);
+      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
+      goto err;
+    }
+
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
+      typeof(source->total_sectors) max_crypt_sectors = 0;
+
+      grub_errno = GRUB_ERR_NONE;
       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
       if (ret)
 	goto err;
+      if (grub_errno != GRUB_ERR_NONE)
+	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
 
       if (keyslot.priority == 0)
 	{
@@ -616,11 +630,68 @@ luks2_recover_key (grub_disk_t source,
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      /* Set to the source disk size, which is the maximum we allow. */
+      max_crypt_sectors = grub_disk_convert_sector(source,
+						   source->total_sectors,
+						   crypt->log_sector_size);
+
+      if (max_crypt_sectors < crypt->offset_sectors)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
+				 " greater than source disk size, skipping\n",
+				 segment.slot_key);
+	  continue;
+	}
+
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
-			       - crypt->offset_sectors;
+	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	{
+	  grub_errno = GRUB_ERR_NONE;
+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	  if (grub_errno == GRUB_ERR_NONE)
+	    ;
+	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
+	    {
+	      /* TODO: Unparsable number-string, try to use the whole disk */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " is not a parsable number\n",
+				     segment.slot_key);
+	      continue;
+	    }
+	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
+	    {
+	      /*
+	       * There was an overflow in parsing segment.size, so disk must
+	       * be very large or the string is incorrect.
+	       */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " overflowed 64-bit unsigned integer,"
+				     " the end of the crypto device will be"
+				     " inaccessible\n",
+				     segment.slot_key);
+	      if (crypt->total_sectors > max_crypt_sectors)
+		crypt->total_sectors = max_crypt_sectors;
+	    }
+	}
+
+      if (crypt->total_sectors == 0)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
+				 " sectors, skipping\n",
+				 segment.slot_key);
+	  continue;
+	}
+      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
+				 " data position greater than source disk size,"
+				 " the end of the crypto device will be"
+				 " inaccessible\n",
+				 segment.slot_key);
+	  /* Allow decryption up to the end of the source disk. */
+	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
+	}
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 132a1bb75..1a9e8fcf4 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -174,6 +174,22 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* Return value of grub_disk_get_size() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
+/* Convert sector number from disk sized sectors to a log-size sized sector. */
+static inline grub_disk_addr_t
+grub_disk_convert_sector (grub_disk_t disk,
+			  grub_disk_addr_t sector,
+			  grub_size_t log_sector_size)
+{
+  if (disk->log_sector_size < log_sector_size)
+    {
+      /* Round up to the nearest log_sector_size sized sector. */
+      sector += 1ULL << ((log_sector_size / disk->log_sector_size) - 1);
+      return sector >> (log_sector_size - disk->log_sector_size);
+    }
+  else
+    return sector << (disk->log_sector_size - log_sector_size);
+}
+
 /* Convert to GRUB native disk sized sector from disk sized sector. */
 static inline grub_disk_addr_t
 grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
-- 
2.27.0



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

* [PATCH v5 07/11] luks2: Error check segment.sector_size
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (5 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 06/11] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 08/11] whitespace: convert 8 spaces to tabs Glenn Washburn
                             ` (3 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2f2515fb6..0d838f2e0 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -626,6 +626,17 @@ luks2_recover_key (grub_disk_t source,
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
+      /* Sector size should be one of 512, 1024, 2048, or 4096. */
+      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
+	    segment.sector_size == 2048 || segment.sector_size == 4096))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
+				 " size %"PRIuGRUB_UINT64_T" is not one of"
+				 " 512, 1024, 2048, or 4096\n",
+				 segment.slot_key, segment.sector_size);
+	  continue;
+	}
+
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
-- 
2.27.0



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

* [PATCH v5 08/11] whitespace: convert 8 spaces to tabs.
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (6 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 07/11] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 09/11] mips: Enable __clzdi2() Glenn Washburn
                             ` (2 subsequent siblings)
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 0d838f2e0..7e7b79d17 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -279,8 +279,8 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     {
       if (grub_json_getchild (&digest, &digests, i) ||
 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
-          grub_json_getchild (&digest, &digest, 0) ||
-          luks2_parse_digest (d, &digest))
+	  grub_json_getchild (&digest, &digest, 0) ||
+	  luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->slot_key)))
@@ -298,7 +298,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       if (grub_json_getchild (&segment, &segments, i) ||
 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
-          luks2_parse_segment (s, &segment))
+	  luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->slot_key)))
@@ -622,7 +622,7 @@ luks2_recover_key (grub_disk_t source,
 	{
 	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
-        }
+	}
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
-- 
2.27.0



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

* [PATCH v5 09/11] mips: Enable __clzdi2()
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (7 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 08/11] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 10/11] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 11/11] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
__clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
enabled.

Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
---
 grub-core/kern/compiler-rt.c | 2 +-
 include/grub/compiler-rt.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index a464200c6..2057c2e0c 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
 }
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 __clzdi2 (grub_uint64_t val)
 {
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
index 7591980b4..17828b322 100644
--- a/include/grub/compiler-rt.h
+++ b/include/grub/compiler-rt.h
@@ -115,7 +115,7 @@ int
 EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
 #endif
-- 
2.27.0



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

* [PATCH v5 10/11] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (8 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 09/11] mips: Enable __clzdi2() Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  2020-11-23  5:23           ` [PATCH v5 11/11] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 include/grub/misc.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index b7ca6dd58..85a481f0c 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 
+#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
+                         - __builtin_clzll (n) - 1)
+
 #endif /* ! GRUB_MISC_HEADER */
-- 
2.27.0



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

* [PATCH v5 11/11] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
                             ` (9 preceding siblings ...)
  2020-11-23  5:23           ` [PATCH v5 10/11] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-11-23  5:23           ` Glenn Washburn
  10 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-23  5:23 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 7e7b79d17..de3933be8 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -639,8 +639,7 @@ luks2_recover_key (grub_disk_t source,
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
-      crypt->log_sector_size = sizeof (unsigned int) * 8
-		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      crypt->log_sector_size = grub_log2ull (segment.sector_size);
       /* Set to the source disk size, which is the maximum we allow. */
       max_crypt_sectors = grub_disk_convert_sector(source,
 						   source->total_sectors,
-- 
2.27.0



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

* [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (16 preceding siblings ...)
  2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
@ 2020-11-27  9:03         ` Glenn Washburn
  2020-11-27  9:03           ` [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
                             ` (11 more replies)
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
  19 siblings, 12 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This is a minor update to v5. There's a commit message fix, changes to debug
messages to add some more information on error, and an extra patch which
removes unused arguments to grub_error in luks2_parse_segment and
luks2_parse_digest.

Glenn

Glenn Washburn (12):
  luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  luks2: Use more intuitive slot key instead of index in user messages.
  luks2: Remove unused argument in grub_error
  cryptodisk: Replace some literals with constants in
    grub_cryptodisk_endecrypt
  luks2: grub_cryptodisk_t->total_sectors is the max number of device
    native sectors
  cryptodisk: Properly handle non-512 byte sized sectors
  luks2: Better error handling when setting up the cryptodisk
  luks2: Error check segment.sector_size
  whitespace: convert 8 spaces to tabs.
  mips: Enable __clzdi2()
  misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
    integers
  luks2: Use grub_log2ull to calculate log_sector_size and improve
    readability

 grub-core/disk/cryptodisk.c  |  64 +++++++++------
 grub-core/disk/luks.c        |   5 +-
 grub-core/disk/luks2.c       | 153 ++++++++++++++++++++++++++++-------
 grub-core/kern/compiler-rt.c |   2 +-
 include/grub/compiler-rt.h   |   2 +-
 include/grub/cryptodisk.h    |   8 +-
 include/grub/disk.h          |  16 ++++
 include/grub/misc.h          |   3 +
 include/grub/types.h         |   5 ++
 9 files changed, 198 insertions(+), 60 deletions(-)

Range-diff against v5:
 1:  e2fbfa3ad =  1:  6262aefe9 luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
 2:  a7be73eb2 !  2:  3cd52834b luks: Use more intuitive slot key instead of index in user messages.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks: Use more intuitive slot key instead of index in user messages.
    +    luks2: Use more intuitive slot key instead of index in user messages.
     
         Use the slot key name in the json array rather than the 0 based index in the
         json array for keyslots, segments, and digests. This is less confusing for
 -:  --------- >  3:  8527be145 luks2: Remove unused argument in grub_error
 3:  2598569ee =  4:  1a248b679 cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
 4:  6d67abeb4 =  5:  45f5d644f luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
 5:  450a8b5a7 =  6:  6e01cafb1 cryptodisk: Properly handle non-512 byte sized sectors
 6:  268cceda5 !  7:  d8927c6bc luks2: Better error handling when setting up the cryptodisk
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +      if (max_crypt_sectors < crypt->offset_sectors)
     +	{
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
    -+				 " greater than source disk size, skipping\n",
    -+				 segment.slot_key);
    ++				 " %"PRIuGRUB_UINT64_T" which is greater than"
    ++				 " source disk size %"PRIuGRUB_UINT64_T","
    ++				 " skipping\n",
    ++				 segment.slot_key, crypt->offset_sectors,
    ++				 max_crypt_sectors);
     +	  continue;
     +	}
     +
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	    {
     +	      /* TODO: Unparsable number-string, try to use the whole disk */
     +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
    -+				     " is not a parsable number\n",
    -+				     segment.slot_key);
    ++				     " \"%s\" is not a parsable number\n",
    ++				     segment.slot_key, segment.size);
     +	      continue;
     +	    }
     +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	       * be very large or the string is incorrect.
     +	       */
     +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
    -+				     " overflowed 64-bit unsigned integer,"
    ++				     " %s overflowed 64-bit unsigned integer,"
     +				     " the end of the crypto device will be"
     +				     " inaccessible\n",
    -+				     segment.slot_key);
    ++				     segment.slot_key, segment.size);
     +	      if (crypt->total_sectors > max_crypt_sectors)
     +		crypt->total_sectors = max_crypt_sectors;
     +	    }
 7:  cce3b042e =  8:  fcd7aadb7 luks2: Error check segment.sector_size
 8:  249967edc =  9:  61f77a1a8 whitespace: convert 8 spaces to tabs.
 9:  88490d61e = 10:  d71d26701 mips: Enable __clzdi2()
10:  5f3ae1e2d = 11:  8aa295f77 misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
11:  cc56ab2a0 = 12:  7050a4ace luks2: Use grub_log2ull to calculate log_sector_size and improve readability
-- 
2.27.0



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

* [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-02 17:01             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
                             ` (10 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows code using these structs to know the named key associated with
these json data structures. In the future we can use these to provide better
error messages to the user.

Get rid of idx variable in luks2_get_keyslot which was overloaded to be used
for both keyslot and segment slot keys.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d96764a02..ab2c31dcd 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  grub_uint64_t slot_key;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
 
 struct grub_luks2_segment
 {
+  grub_uint64_t slot_key;
   grub_uint64_t offset;
   const char	*size;
   const char	*encryption;
@@ -112,6 +114,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
 
 struct grub_luks2_digest
 {
+  grub_uint64_t slot_key;
   /* Both keyslots and segments are interpreted as bitfields here */
   grub_uint64_t	keyslots;
   grub_uint64_t	segments;
@@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t idx;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
@@ -276,11 +278,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
@@ -293,12 +296,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&segment, &segments, i) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << s->slot_key)))
 	break;
     }
   if (i == size)
-- 
2.27.0



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

* [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages.
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-11-27  9:03           ` [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-02 17:23             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 03/12] luks2: Remove unused argument in grub_error Glenn Washburn
                             ` (9 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the slot key name in the json array rather than the 0 based index in the
json array for keyslots, segments, and digests. This is less confusing for
the end user. For example, say you have a LUKS2 device with a key in slot 1
and slot 4. When using the password for slot 4 to unlock the device, the
messages using the index of the keyslot will mention keyslot 1 (its a
zero-based index). Furthermore, with this change the keyslot number will
align with the number used to reference the keyslot when using the
--key-slot argument to cryptsetup. Error messages now distinguish between
indexes and slot keys. The former include the string "index" in the error
string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index ab2c31dcd..c390ea3e6 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -269,7 +269,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -281,13 +281,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->slot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -299,13 +299,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->slot_key)))
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
 
   return GRUB_ERR_NONE;
 }
@@ -601,11 +601,11 @@ luks2_recover_key (grub_disk_t source,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -620,16 +620,16 @@ luks2_recover_key (grub_disk_t source,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -637,7 +637,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v6 03/12] luks2: Remove unused argument in grub_error
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-11-27  9:03           ` [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
  2020-11-27  9:03           ` [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-02 17:24             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
                             ` (8 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c390ea3e6..619e57aad 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -203,7 +203,7 @@ luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
       grub_json_getstring (&out->size, segment, "size") ||
       grub_json_getstring (&out->encryption, segment, "encryption") ||
       grub_json_getint64 (&out->sector_size, segment, "sector_size"))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters", type);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters");
 
   return GRUB_ERR_NONE;
 }
@@ -231,7 +231,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no segments", type);
+		       "Digest references no segments");
 
   for (i = 0; i < size; i++)
     {
@@ -243,7 +243,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &keyslots))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no keyslots", type);
+		       "Digest references no keyslots");
 
   for (i = 0; i < size; i++)
     {
-- 
2.27.0



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

* [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (2 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 03/12] luks2: Remove unused argument in grub_error Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-02 17:37             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
                             ` (7 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This should improve readability of code by providing clues as to what the
value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
bits allocated for type. Also add GRUB_TYPE_U_MAX/MIN(type) macros to get
the max/min values for an unsigned number with size of type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 13 +++++++------
 include/grub/types.h        |  5 +++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 473c93976..31b73c535 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  iv[1] = grub_cpu_to_le32 (sector >> 32);
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
+					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index f22055f98..29d807f71 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -72,6 +72,8 @@
 # endif
 #endif
 
+#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
+
 #ifndef __CHAR_BIT__
 # error __CHAR_BIT__ is not defined
 #elif __CHAR_BIT__ != 8
@@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof (type))(~0)))
+#define GRUB_TYPE_U_MIN(type) 0ULL
+
 typedef grub_uint64_t grub_properly_aligned_t;
 
 #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
-- 
2.27.0



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

* [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (3 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-02 17:56             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                             ` (6 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

We need to convert the sectors from the size of the underlying device to the
cryptodisk sector size; segment.size is in bytes which need to be converted
to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
returns the total number of device native sectors.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 619e57aad..0c814bd7c 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -426,7 +426,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -612,9 +612,10 @@ luks2_recover_key (grub_disk_t source,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
+			       - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (4 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 13:04             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
                             ` (5 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 31b73c535..b62835acc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t iv64;
+
+	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    grub_set_unaligned64 (iv, iv64);
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+	  /* The IV is the 64 bit byte offset of the sector. */
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
-					       - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+					       - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index aa9877b68..84c3fa73a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  GRUB_LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 0c814bd7c..b7ed0642e 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -501,7 +501,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      GRUB_LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index c9bf7597a..938912cf3 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -144,7 +150,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (5 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 13:31             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 08/12] luks2: Error check segment.sector_size Glenn Washburn
                             ` (4 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

First, check to make sure that source disk has a known size. If not, print
debug message and return error. There are 4 cases where
GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
all those cases processing continues. So this is probably a bit
conservative. However, 3 of the cases seem pathological, and the other,
biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
volume on a cd is a big use case, we'll error until someone complains.

Do some sanity checking on data coming from the luks header. If segment.size
is "dynamic",

Check for errors from grub_strtoull when converting segment size from
string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
returned, then there was an overflow in converting to a 64-bit unsigned
integer. So this could be a very large disk (perhaps large raid array).
In this case, we want to continue to try to use this key so long as the
source disk's size is greater than this segment size. Otherwise, this is
an invalid segment, and continue on to the next key.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 80 ++++++++++++++++++++++++++++++++++++++++--
 include/grub/disk.h    | 16 +++++++++
 2 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index b7ed0642e..01f9608e5 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
       goto err;
     }
 
+  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+    {
+      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
+      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
+			     "conservatively returning error\n", source->name);
+      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
+      goto err;
+    }
+
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
+      typeof(source->total_sectors) max_crypt_sectors = 0;
+
+      grub_errno = GRUB_ERR_NONE;
       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
       if (ret)
 	goto err;
+      if (grub_errno != GRUB_ERR_NONE)
+	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
 
       if (keyslot.priority == 0)
 	{
@@ -616,11 +630,71 @@ luks2_recover_key (grub_disk_t source,
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      /* Set to the source disk size, which is the maximum we allow. */
+      max_crypt_sectors = grub_disk_convert_sector(source,
+						   source->total_sectors,
+						   crypt->log_sector_size);
+
+      if (max_crypt_sectors < crypt->offset_sectors)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
+				 " %"PRIuGRUB_UINT64_T" which is greater than"
+				 " source disk size %"PRIuGRUB_UINT64_T","
+				 " skipping\n",
+				 segment.slot_key, crypt->offset_sectors,
+				 max_crypt_sectors);
+	  continue;
+	}
+
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
-			       - crypt->offset_sectors;
+	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	{
+	  grub_errno = GRUB_ERR_NONE;
+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	  if (grub_errno == GRUB_ERR_NONE)
+	    ;
+	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
+	    {
+	      /* TODO: Unparsable number-string, try to use the whole disk */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " \"%s\" is not a parsable number\n",
+				     segment.slot_key, segment.size);
+	      continue;
+	    }
+	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
+	    {
+	      /*
+	       * There was an overflow in parsing segment.size, so disk must
+	       * be very large or the string is incorrect.
+	       */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " %s overflowed 64-bit unsigned integer,"
+				     " the end of the crypto device will be"
+				     " inaccessible\n",
+				     segment.slot_key, segment.size);
+	      if (crypt->total_sectors > max_crypt_sectors)
+		crypt->total_sectors = max_crypt_sectors;
+	    }
+	}
+
+      if (crypt->total_sectors == 0)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
+				 " sectors, skipping\n",
+				 segment.slot_key);
+	  continue;
+	}
+      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
+				 " data position greater than source disk size,"
+				 " the end of the crypto device will be"
+				 " inaccessible\n",
+				 segment.slot_key);
+	  /* Allow decryption up to the end of the source disk. */
+	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
+	}
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 132a1bb75..1a9e8fcf4 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -174,6 +174,22 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* Return value of grub_disk_get_size() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
+/* Convert sector number from disk sized sectors to a log-size sized sector. */
+static inline grub_disk_addr_t
+grub_disk_convert_sector (grub_disk_t disk,
+			  grub_disk_addr_t sector,
+			  grub_size_t log_sector_size)
+{
+  if (disk->log_sector_size < log_sector_size)
+    {
+      /* Round up to the nearest log_sector_size sized sector. */
+      sector += 1ULL << ((log_sector_size / disk->log_sector_size) - 1);
+      return sector >> (log_sector_size - disk->log_sector_size);
+    }
+  else
+    return sector << (disk->log_sector_size - log_sector_size);
+}
+
 /* Convert to GRUB native disk sized sector from disk sized sector. */
 static inline grub_disk_addr_t
 grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
-- 
2.27.0



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

* [PATCH v6 08/12] luks2: Error check segment.sector_size
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (6 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 13:52             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 09/12] whitespace: convert 8 spaces to tabs Glenn Washburn
                             ` (3 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 01f9608e5..f2313cb0f 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -626,6 +626,17 @@ luks2_recover_key (grub_disk_t source,
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
+      /* Sector size should be one of 512, 1024, 2048, or 4096. */
+      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
+	    segment.sector_size == 2048 || segment.sector_size == 4096))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
+				 " size %"PRIuGRUB_UINT64_T" is not one of"
+				 " 512, 1024, 2048, or 4096\n",
+				 segment.slot_key, segment.sector_size);
+	  continue;
+	}
+
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
-- 
2.27.0



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

* [PATCH v6 09/12] whitespace: convert 8 spaces to tabs.
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (7 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 08/12] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 13:53             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 10/12] mips: Enable __clzdi2() Glenn Washburn
                             ` (2 subsequent siblings)
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index f2313cb0f..c2129f929 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -279,8 +279,8 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     {
       if (grub_json_getchild (&digest, &digests, i) ||
 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
-          grub_json_getchild (&digest, &digest, 0) ||
-          luks2_parse_digest (d, &digest))
+	  grub_json_getchild (&digest, &digest, 0) ||
+	  luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->slot_key)))
@@ -298,7 +298,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       if (grub_json_getchild (&segment, &segments, i) ||
 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
-          luks2_parse_segment (s, &segment))
+	  luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->slot_key)))
@@ -622,7 +622,7 @@ luks2_recover_key (grub_disk_t source,
 	{
 	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
 	  continue;
-        }
+	}
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
 
-- 
2.27.0



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

* [PATCH v6 10/12] mips: Enable __clzdi2()
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (8 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 09/12] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 14:00             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
  2020-11-27  9:03           ` [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
__clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
enabled.

Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
---
 grub-core/kern/compiler-rt.c | 2 +-
 include/grub/compiler-rt.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index a464200c6..2057c2e0c 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
 }
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 __clzdi2 (grub_uint64_t val)
 {
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
index 7591980b4..17828b322 100644
--- a/include/grub/compiler-rt.h
+++ b/include/grub/compiler-rt.h
@@ -115,7 +115,7 @@ int
 EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
 #endif
-- 
2.27.0



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

* [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (9 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 10/12] mips: Enable __clzdi2() Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 14:02             ` Daniel Kiper
  2020-11-27  9:03           ` [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 include/grub/misc.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index b7ca6dd58..85a481f0c 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 
+#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
+                         - __builtin_clzll (n) - 1)
+
 #endif /* ! GRUB_MISC_HEADER */
-- 
2.27.0



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

* [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (10 preceding siblings ...)
  2020-11-27  9:03           ` [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-11-27  9:03           ` Glenn Washburn
  2020-12-03 14:13             ` Daniel Kiper
  11 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-11-27  9:03 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c2129f929..173a14197 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -639,8 +639,7 @@ luks2_recover_key (grub_disk_t source,
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
-      crypt->log_sector_size = sizeof (unsigned int) * 8
-		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      crypt->log_sector_size = grub_log2ull (segment.sector_size);
       /* Set to the source disk size, which is the maximum we allow. */
       max_crypt_sectors = grub_disk_convert_sector(source,
 						   source->total_sectors,
-- 
2.27.0



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

* Re: [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-11-27  9:03           ` [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-12-02 17:01             ` Daniel Kiper
  2020-12-03  7:23               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-02 17:01 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:33AM -0600, Glenn Washburn wrote:
> This allows code using these structs to know the named key associated with
> these json data structures. In the future we can use these to provide better
> error messages to the user.
>
> Get rid of idx variable in luks2_get_keyslot which was overloaded to be used

I prefer if you add "()" to the function names, i.e. luks2_get_keyslot(), in
the comments and commit messages. This way it is easier to understand what
you mean.

> for both keyslot and segment slot keys.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index d96764a02..ab2c31dcd 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -65,6 +65,7 @@ typedef struct grub_luks2_header grub_luks2_header_t;
>
>  struct grub_luks2_keyslot
>  {
> +  grub_uint64_t slot_key;

Could you be more consistent and use keyslot instead of slot_key here?

>    grub_int64_t key_size;
>    grub_int64_t priority;
>    struct
> @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
>
>  struct grub_luks2_segment
>  {
> +  grub_uint64_t slot_key;

Ditto. The code below uses keyslot instead...

>    grub_uint64_t offset;
>    const char	*size;
>    const char	*encryption;
> @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
>
>  struct grub_luks2_digest
>  {
> +  grub_uint64_t slot_key;
>    /* Both keyslots and segments are interpreted as bitfields here */
>    grub_uint64_t	keyslots;
>    grub_uint64_t	segments;
> @@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t idx;
>
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||

Daniel


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

* Re: [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages.
  2020-11-27  9:03           ` [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
@ 2020-12-02 17:23             ` Daniel Kiper
  2020-12-03  7:24               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-02 17:23 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:34AM -0600, Glenn Washburn wrote:
> Use the slot key name in the json array rather than the 0 based index in the
> json array for keyslots, segments, and digests. This is less confusing for
> the end user. For example, say you have a LUKS2 device with a key in slot 1
> and slot 4. When using the password for slot 4 to unlock the device, the
> messages using the index of the keyslot will mention keyslot 1 (its a
> zero-based index). Furthermore, with this change the keyslot number will
> align with the number used to reference the keyslot when using the
> --key-slot argument to cryptsetup. Error messages now distinguish between
> indexes and slot keys. The former include the string "index" in the error
> string, and the later are surrounded in quotes.

This should be split into two separate patches. One should add "index"
to the messages another should add quotes. Well, I am not convinced
that quotes are good differentiators... I would drop them or rephrase
messages to really differentiate indexes and slot keys.

> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index ab2c31dcd..c390ea3e6 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -269,7 +269,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>        grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
>
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
> @@ -281,13 +281,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>
>        if ((d->keyslots & (1 << k->slot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
>
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -299,13 +299,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>
>        if ((d->segments & (1 << s->slot_key)))
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
>
>    return GRUB_ERR_NONE;
>  }
> @@ -601,11 +601,11 @@ luks2_recover_key (grub_disk_t source,
>
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);

Quotes are missing?

>  	  continue;
>          }
>
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);

Ditto...

>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -620,16 +620,16 @@ luks2_recover_key (grub_disk_t source,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",

Ditto and below...

> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>
> @@ -637,7 +637,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);

Daniel


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

* Re: [PATCH v6 03/12] luks2: Remove unused argument in grub_error
  2020-11-27  9:03           ` [PATCH v6 03/12] luks2: Remove unused argument in grub_error Glenn Washburn
@ 2020-12-02 17:24             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-02 17:24 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:35AM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
  2020-11-27  9:03           ` [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
@ 2020-12-02 17:37             ` Daniel Kiper
  2020-12-03  8:29               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-02 17:37 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:36AM -0600, Glenn Washburn wrote:
> This should improve readability of code by providing clues as to what the
> value represents. The new macro GRUB_TYPE_BITS(type) returns the number of
> bits allocated for type. Also add GRUB_TYPE_U_MAX/MIN(type) macros to get
> the max/min values for an unsigned number with size of type.

Two separate patches please...

> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 13 +++++++------
>  include/grub/types.h        |  5 +++++
>  2 files changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 473c93976..31b73c535 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  iv[1] = grub_cpu_to_le32 (sector >> 32);
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> +					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index f22055f98..29d807f71 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -72,6 +72,8 @@
>  # endif
>  #endif
>
> +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)

This macro should go below "#ifndef __CHAR_BIT__ ...".

>  #ifndef __CHAR_BIT__
>  # error __CHAR_BIT__ is not defined
>  #elif __CHAR_BIT__ != 8
> @@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
>  #endif
>  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
>
> +#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof (type))(~0)))

(typeof (1ULL)) == (unsigned long long)?

> +#define GRUB_TYPE_U_MIN(type) 0ULL

I am not sure why you cast everything to ULL/unsigned long long. Should
not the final cast be to (typeof (type))?

Daniel


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

* Re: [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-11-27  9:03           ` [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-12-02 17:56             ` Daniel Kiper
  2020-12-03  8:54               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-02 17:56 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:37AM -0600, Glenn Washburn wrote:
> We need to convert the sectors from the size of the underlying device to the
> cryptodisk sector size; segment.size is in bytes which need to be converted
> to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
> returns the total number of device native sectors.

Should not we change the name to, e.g., grub_disk_native_sectors() then?
Could you do that?

> Also, removed an empty statement.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-02 17:01             ` Daniel Kiper
@ 2020-12-03  7:23               ` Glenn Washburn
  2020-12-03 12:35                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03  7:23 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Wed, 2 Dec 2020 18:01:47 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:33AM -0600, Glenn Washburn wrote:
> > This allows code using these structs to know the named key
> > associated with these json data structures. In the future we can
> > use these to provide better error messages to the user.
> >
> > Get rid of idx variable in luks2_get_keyslot which was overloaded
> > to be used
> 
> I prefer if you add "()" to the function names, i.e.
> luks2_get_keyslot(), in the comments and commit messages. This way it
> is easier to understand what you mean.

Ok.

> > for both keyslot and segment slot keys.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 13 ++++++++-----
> >  1 file changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index d96764a02..ab2c31dcd 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -65,6 +65,7 @@ typedef struct grub_luks2_header
> > grub_luks2_header_t;
> >
> >  struct grub_luks2_keyslot
> >  {
> > +  grub_uint64_t slot_key;
> 
> Could you be more consistent and use keyslot instead of slot_key here?

I intentionally chose not to use keyslot because I thought it was
confusing.  slot_key is not a keyslot in the sense of a slot for a
cryptographic key or key material as in the usage keyslot in the struct
named "grub_luks2_keyslot".  Its the key value of a "slot" in a json
associative array which is modeling a sparse array.  Perhaps just "key"
might be more to your liking?

> >    grub_int64_t key_size;
> >    grub_int64_t priority;
> >    struct
> > @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot
> > grub_luks2_keyslot_t;
> >
> >  struct grub_luks2_segment
> >  {
> > +  grub_uint64_t slot_key;
> 
> Ditto. The code below uses keyslot instead...
> 
> >    grub_uint64_t offset;
> >    const char	*size;
> >    const char	*encryption;
> > @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment
> > grub_luks2_segment_t;
> >
> >  struct grub_luks2_digest
> >  {
> > +  grub_uint64_t slot_key;
> >    /* Both keyslots and segments are interpreted as bitfields here
> > */ grub_uint64_t	keyslots;
> >    grub_uint64_t	segments;
> > @@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s {
> >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > segment; grub_size_t i, size;
> > -  grub_uint64_t idx;
> >
> >    /* Get nth keyslot */
> >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
> 
> Daniel


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

* Re: [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages.
  2020-12-02 17:23             ` Daniel Kiper
@ 2020-12-03  7:24               ` Glenn Washburn
  2020-12-03 12:39                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03  7:24 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Wed, 2 Dec 2020 18:23:08 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:34AM -0600, Glenn Washburn wrote:
> > Use the slot key name in the json array rather than the 0 based
> > index in the json array for keyslots, segments, and digests. This
> > is less confusing for the end user. For example, say you have a
> > LUKS2 device with a key in slot 1 and slot 4. When using the
> > password for slot 4 to unlock the device, the messages using the
> > index of the keyslot will mention keyslot 1 (its a zero-based
> > index). Furthermore, with this change the keyslot number will align
> > with the number used to reference the keyslot when using the
> > --key-slot argument to cryptsetup. Error messages now distinguish
> > between indexes and slot keys. The former include the string
> > "index" in the error string, and the later are surrounded in quotes.
> 
> This should be split into two separate patches. One should add "index"
> to the messages another should add quotes. Well, I am not convinced
> that quotes are good differentiators... I would drop them or rephrase
> messages to really differentiate indexes and slot keys.

I thought the quotes would make more intuitive sense to a user because
the value would also be quoted in the json which would be output when
using cryptosetup with --debug-json.  I can split it in to two patches,
but just tell me how you want me to rephrase and I will.  No need for
another round of reviews.

> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 24 ++++++++++++------------
> >  1 file changed, 12 insertions(+), 12 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index ab2c31dcd..c390ea3e6 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -269,7 +269,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s grub_json_getuint64
> > (&k->slot_key, &keyslot, NULL) || grub_json_getchild (&keyslot,
> > &keyslot, 0) || luks2_parse_keyslot (k, &keyslot))
> > -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> > +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
> >
> >    /* Get digest that matches the keyslot. */
> >    if (grub_json_getvalue (&digests, root, "digests") ||
> > @@ -281,13 +281,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s grub_json_getuint64
> > (&d->slot_key, &digest, NULL) || grub_json_getchild (&digest,
> > &digest, 0) || luks2_parse_digest (d, &digest))
> > -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > digest %"PRIuGRUB_SIZE, i);
> > +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > digest index %"PRIuGRUB_SIZE, i);
> >
> >        if ((d->keyslots & (1 << k->slot_key)))
> >  	break;
> >      }
> >    if (i == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> >
> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> > @@ -299,13 +299,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s grub_json_getuint64
> > (&s->slot_key, &segment, NULL) || grub_json_getchild (&segment,
> > &segment, 0) || luks2_parse_segment (s, &segment))
> > -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > segment %"PRIuGRUB_SIZE, i);
> > +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > segment index %"PRIuGRUB_SIZE, i);
> >
> >        if ((d->segments & (1 << s->slot_key)))
> >  	break;
> >      }
> >    if (i == size)
> > -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest %"PRIuGRUB_SIZE);
> > +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> >
> >    return GRUB_ERR_NONE;
> >  }
> > @@ -601,11 +601,11 @@ luks2_recover_key (grub_disk_t source,
> >
> >        if (keyslot.priority == 0)
> >  	{
> > -	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_SIZE" due to priority\n", i);
> > +	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
> 
> Quotes are missing?

Yep. good catch.

> >  	  continue;
> >          }
> >
> > -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n",
> > i);
> > +      grub_dprintf ("luks2", "Trying keyslot
> > %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
> 
> Ditto...
> 
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); @@ -620,16 +620,16 @@ luks2_recover_key
> > (grub_disk_t source, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_SIZE" failed: %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_UINT64_T" failed: %s\n",
> 
> Ditto and below...
> 
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >
> >        ret = luks2_verify_key (&digest, candidate_key,
> > keyslot.key_size); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_SIZE": %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_UINT64_T": %s\n",
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >
> > @@ -637,7 +637,7 @@ luks2_recover_key (grub_disk_t source,
> >         * TRANSLATORS: It's a cryptographic key slot: one element
> > of an array
> >         * where each element is either empty or holds a key.
> >         */
> > -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> > +      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"),
> > keyslot.slot_key);
> 
> Daniel

Glenn


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

* Re: [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
  2020-12-02 17:37             ` Daniel Kiper
@ 2020-12-03  8:29               ` Glenn Washburn
  2020-12-03 12:44                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03  8:29 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Wed, 2 Dec 2020 18:37:42 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:36AM -0600, Glenn Washburn wrote:
> > This should improve readability of code by providing clues as to
> > what the value represents. The new macro GRUB_TYPE_BITS(type)
> > returns the number of bits allocated for type. Also add
> > GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> > unsigned number with size of type.
> 
> Two separate patches please...

Ok.

> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/cryptodisk.c | 13 +++++++------
> >  include/grub/types.h        |  5 +++++
> >  2 files changed, 12 insertions(+), 6 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index 473c93976..31b73c535 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, iv[1] = grub_cpu_to_le32 (sector >> 32);
> >  	  /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > dev->log_sector_size));
> > +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > (iv[1])
> > +					       -
> > dev->log_sector_size)); iv[0] = grub_cpu_to_le32 ((sector <<
> > dev->log_sector_size)
> > -				    & 0xFFFFFFFF);
> > +				    & GRUB_TYPE_U_MAX (iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >  	  {
> >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> > -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS
> > (iv[0]));
> > +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX
> > (iv[0])); }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >  					 dev->cipher->cipher->blocksize);
> >  	  if (err)
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index f22055f98..29d807f71 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -72,6 +72,8 @@
> >  # endif
> >  #endif
> >
> > +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> 
> This macro should go below "#ifndef __CHAR_BIT__ ...".

Ack.

> >  #ifndef __CHAR_BIT__
> >  # error __CHAR_BIT__ is not defined
> >  #elif __CHAR_BIT__ != 8
> > @@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
> >  #endif
> >  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
> >
> > +#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof
> > (type))(~0)))
> 
> (typeof (1ULL)) == (unsigned long long)?

I'll change it.

> > +#define GRUB_TYPE_U_MIN(type) 0ULL
> 
> I am not sure why you cast everything to ULL/unsigned long long.
> Should not the final cast be to (typeof (type))?

I think that to as great as an extent as possible macros should behave
like functions.  So in this case, its "return type" should not change
depending on the input arguments.  This can be confusing and the source
of errors.  Sure, you can say that the user of the macro can just do
the cast herself, but why add potentially unnecessary steps.

Also, I wanted to unsure that the result was an unsigned type,
regardless of signedness of input type. And using the largest unsigned
type seemed the best because I don't know how to take an arbitrary
integer type can only convert its signedness.

But at this point, I really don't care.  Tell me what you want it to be
and I'll make it so.

Glenn


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

* Re: [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-02 17:56             ` Daniel Kiper
@ 2020-12-03  8:54               ` Glenn Washburn
  2020-12-03 12:45                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03  8:54 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Wed, 2 Dec 2020 18:56:46 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:37AM -0600, Glenn Washburn wrote:
> > We need to convert the sectors from the size of the underlying
> > device to the cryptodisk sector size; segment.size is in bytes
> > which need to be converted to cryptodisk sectors as well. And
> > counter-intuitively, grub_disk_get_size returns the total number of
> > device native sectors.
> 
> Should not we change the name to, e.g., grub_disk_native_sectors()
> then? Could you do that?

Sure, I can do that.

> > Also, removed an empty statement.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> 
> Daniel


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

* Re: [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-03  7:23               ` Glenn Washburn
@ 2020-12-03 12:35                 ` Daniel Kiper
  2020-12-03 16:46                   ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 12:35 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 01:23:17AM -0600, Glenn Washburn wrote:
> On Wed, 2 Dec 2020 18:01:47 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:33AM -0600, Glenn Washburn wrote:
> > > This allows code using these structs to know the named key
> > > associated with these json data structures. In the future we can
> > > use these to provide better error messages to the user.
> > >
> > > Get rid of idx variable in luks2_get_keyslot which was overloaded
> > > to be used
> >
> > I prefer if you add "()" to the function names, i.e.
> > luks2_get_keyslot(), in the comments and commit messages. This way it
> > is easier to understand what you mean.
>
> Ok.
>
> > > for both keyslot and segment slot keys.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 13 ++++++++-----
> > >  1 file changed, 8 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index d96764a02..ab2c31dcd 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -65,6 +65,7 @@ typedef struct grub_luks2_header
> > > grub_luks2_header_t;
> > >
> > >  struct grub_luks2_keyslot
> > >  {
> > > +  grub_uint64_t slot_key;
> >
> > Could you be more consistent and use keyslot instead of slot_key here?
>
> I intentionally chose not to use keyslot because I thought it was
> confusing.  slot_key is not a keyslot in the sense of a slot for a
> cryptographic key or key material as in the usage keyslot in the struct
> named "grub_luks2_keyslot".  Its the key value of a "slot" in a json
> associative array which is modeling a sparse array.  Perhaps just "key"
> might be more to your liking?

IMO "key" is more confusing in this context and it would require at
least a comment to clarify what it means. Is not json_slot_key better
then? Probably with some comment what is it too...

> > >    grub_int64_t key_size;
> > >    grub_int64_t priority;
> > >    struct
> > > @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot
> > > grub_luks2_keyslot_t;
> > >
> > >  struct grub_luks2_segment
> > >  {
> > > +  grub_uint64_t slot_key;
> >
> > Ditto. The code below uses keyslot instead...
> >
> > >    grub_uint64_t offset;
> > >    const char	*size;
> > >    const char	*encryption;
> > > @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment
> > > grub_luks2_segment_t;
> > >
> > >  struct grub_luks2_digest
> > >  {
> > > +  grub_uint64_t slot_key;
> > >    /* Both keyslots and segments are interpreted as bitfields here
> > > */ grub_uint64_t	keyslots;
> > >    grub_uint64_t	segments;
> > > @@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > > grub_luks2_digest_t *d, grub_luks2_s {
> > >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > > segment; grub_size_t i, size;
> > > -  grub_uint64_t idx;
> > >
> > >    /* Get nth keyslot */
> > >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> > >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > > +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||

Should not keyslot be renamed to json_slot_key too?

Daniel


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

* Re: [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages.
  2020-12-03  7:24               ` Glenn Washburn
@ 2020-12-03 12:39                 ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 12:39 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 01:24:18AM -0600, Glenn Washburn wrote:
> On Wed, 2 Dec 2020 18:23:08 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:34AM -0600, Glenn Washburn wrote:
> > > Use the slot key name in the json array rather than the 0 based
> > > index in the json array for keyslots, segments, and digests. This
> > > is less confusing for the end user. For example, say you have a
> > > LUKS2 device with a key in slot 1 and slot 4. When using the
> > > password for slot 4 to unlock the device, the messages using the
> > > index of the keyslot will mention keyslot 1 (its a zero-based
> > > index). Furthermore, with this change the keyslot number will align
> > > with the number used to reference the keyslot when using the
> > > --key-slot argument to cryptsetup. Error messages now distinguish
> > > between indexes and slot keys. The former include the string
> > > "index" in the error string, and the later are surrounded in quotes.
> >
> > This should be split into two separate patches. One should add "index"
> > to the messages another should add quotes. Well, I am not convinced
> > that quotes are good differentiators... I would drop them or rephrase
> > messages to really differentiate indexes and slot keys.
>
> I thought the quotes would make more intuitive sense to a user because
> the value would also be quoted in the json which would be output when
> using cryptosetup with --debug-json.  I can split it in to two patches,
> but just tell me how you want me to rephrase and I will.  No need for
> another round of reviews.

OK, let's stick with the quotes then.

Daniel


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

* Re: [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
  2020-12-03  8:29               ` Glenn Washburn
@ 2020-12-03 12:44                 ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 12:44 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 02:29:11AM -0600, Glenn Washburn wrote:
> On Wed, 2 Dec 2020 18:37:42 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:36AM -0600, Glenn Washburn wrote:
> > > This should improve readability of code by providing clues as to
> > > what the value represents. The new macro GRUB_TYPE_BITS(type)
> > > returns the number of bits allocated for type. Also add
> > > GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> > > unsigned number with size of type.
> >
> > Two separate patches please...
>
> Ok.
>
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/cryptodisk.c | 13 +++++++------
> > >  include/grub/types.h        |  5 +++++
> > >  2 files changed, 12 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/grub-core/disk/cryptodisk.c
> > > b/grub-core/disk/cryptodisk.c index 473c93976..31b73c535 100644
> > > --- a/grub-core/disk/cryptodisk.c
> > > +++ b/grub-core/disk/cryptodisk.c
> > > @@ -284,22 +284,23 @@ grub_cryptodisk_endecrypt (struct
> > > grub_cryptodisk *dev, iv[1] = grub_cpu_to_le32 (sector >> 32);
> > >  	  /* FALLTHROUGH */
> > >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > > (iv[0])); break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> > > -	  iv[1] = grub_cpu_to_le32 (sector >> (32 -
> > > dev->log_sector_size));
> > > +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > > (iv[1])
> > > +					       -
> > > dev->log_sector_size)); iv[0] = grub_cpu_to_le32 ((sector <<
> > > dev->log_sector_size)
> > > -				    & 0xFFFFFFFF);
> > > +				    & GRUB_TYPE_U_MAX (iv[0]));
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> > >  	  {
> > >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> > > -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> > > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > > +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS
> > > (iv[0]));
> > > +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX
> > > (iv[0])); }
> > >  	  break;
> > >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > > (iv[0])); err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> > >  					 dev->cipher->cipher->blocksize);
> > >  	  if (err)
> > > diff --git a/include/grub/types.h b/include/grub/types.h
> > > index f22055f98..29d807f71 100644
> > > --- a/include/grub/types.h
> > > +++ b/include/grub/types.h
> > > @@ -72,6 +72,8 @@
> > >  # endif
> > >  #endif
> > >
> > > +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> >
> > This macro should go below "#ifndef __CHAR_BIT__ ...".
>
> Ack.
>
> > >  #ifndef __CHAR_BIT__
> > >  # error __CHAR_BIT__ is not defined
> > >  #elif __CHAR_BIT__ != 8
> > > @@ -159,6 +161,9 @@ typedef grub_int32_t	grub_ssize_t;
> > >  #endif
> > >  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
> > >
> > > +#define GRUB_TYPE_U_MAX(type) ((typeof (1ULL))((typeof
> > > (type))(~0)))
> >
> > (typeof (1ULL)) == (unsigned long long)?
>
> I'll change it.
>
> > > +#define GRUB_TYPE_U_MIN(type) 0ULL
> >
> > I am not sure why you cast everything to ULL/unsigned long long.
> > Should not the final cast be to (typeof (type))?
>
> I think that to as great as an extent as possible macros should behave
> like functions.  So in this case, its "return type" should not change
> depending on the input arguments.  This can be confusing and the source
> of errors.  Sure, you can say that the user of the macro can just do
> the cast herself, but why add potentially unnecessary steps.
>
> Also, I wanted to unsure that the result was an unsigned type,
> regardless of signedness of input type. And using the largest unsigned
> type seemed the best because I don't know how to take an arbitrary
> integer type can only convert its signedness.
>
> But at this point, I really don't care.  Tell me what you want it to be
> and I'll make it so.

OK, make sense for me. However, please put short comment before macros
why you are casting final result to unsigned long long.

Daniel


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

* Re: [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-03  8:54               ` Glenn Washburn
@ 2020-12-03 12:45                 ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 12:45 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 02:54:19AM -0600, Glenn Washburn wrote:
> On Wed, 2 Dec 2020 18:56:46 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:37AM -0600, Glenn Washburn wrote:
> > > We need to convert the sectors from the size of the underlying
> > > device to the cryptodisk sector size; segment.size is in bytes
> > > which need to be converted to cryptodisk sectors as well. And
> > > counter-intuitively, grub_disk_get_size returns the total number of
> > > device native sectors.
> >
> > Should not we change the name to, e.g., grub_disk_native_sectors()
> > then? Could you do that?
>
> Sure, I can do that.

Thanks!

Daniel


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

* Re: [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors
  2020-11-27  9:03           ` [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-12-03 13:04             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 13:04 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:38AM -0600, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
>
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
>
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk
  2020-11-27  9:03           ` [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-12-03 13:31             ` Daniel Kiper
  2020-12-03 16:24               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 13:31 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:39AM -0600, Glenn Washburn wrote:
> First, check to make sure that source disk has a known size. If not, print
> debug message and return error. There are 4 cases where
> GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
> all those cases processing continues. So this is probably a bit
> conservative. However, 3 of the cases seem pathological, and the other,
> biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
> volume on a cd is a big use case, we'll error until someone complains.
>
> Do some sanity checking on data coming from the luks header. If segment.size
> is "dynamic",
>
> Check for errors from grub_strtoull when converting segment size from
> string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
> not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
> returned, then there was an overflow in converting to a 64-bit unsigned
> integer. So this could be a very large disk (perhaps large raid array).
> In this case, we want to continue to try to use this key so long as the
> source disk's size is greater than this segment size. Otherwise, this is
> an invalid segment, and continue on to the next key.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 80 ++++++++++++++++++++++++++++++++++++++++--
>  include/grub/disk.h    | 16 +++++++++
>  2 files changed, 93 insertions(+), 3 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index b7ed0642e..01f9608e5 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
> +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> +			     "conservatively returning error\n", source->name);
> +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> +      typeof(source->total_sectors) max_crypt_sectors = 0;
> +
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
>        if (ret)
>  	goto err;
> +      if (grub_errno != GRUB_ERR_NONE)
> +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
>
>        if (keyslot.priority == 0)
>  	{
> @@ -616,11 +630,71 @@ luks2_recover_key (grub_disk_t source,
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      /* Set to the source disk size, which is the maximum we allow. */
> +      max_crypt_sectors = grub_disk_convert_sector(source,
> +						   source->total_sectors,
> +						   crypt->log_sector_size);
> +
> +      if (max_crypt_sectors < crypt->offset_sectors)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
> +				 " %"PRIuGRUB_UINT64_T" which is greater than"
> +				 " source disk size %"PRIuGRUB_UINT64_T","
> +				 " skipping\n",
> +				 segment.slot_key, crypt->offset_sectors,
> +				 max_crypt_sectors);
> +	  continue;
> +	}
> +
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	{
> +	  grub_errno = GRUB_ERR_NONE;
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;

I think ">>" should not happen here...

> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;

It should happen here... Or to be exact...
  crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 << crypt->log_sector_size); // Am I right?
  crypt->total_sectors >>= crypt->log_sector_size;

> +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)

Missing space before "("...

> +	    {
> +	      /* TODO: Unparsable number-string, try to use the whole disk */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " \"%s\" is not a parsable number\n",
> +				     segment.slot_key, segment.size);

  crypt->total_sectors = max_crypt_sectors; ?

> +	      continue;

...and then drop continue?

> +	    }
> +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /*
> +	       * There was an overflow in parsing segment.size, so disk must
> +	       * be very large or the string is incorrect.
> +	       */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " %s overflowed 64-bit unsigned integer,"
> +				     " the end of the crypto device will be"
> +				     " inaccessible\n",
> +				     segment.slot_key, segment.size);
> +	      if (crypt->total_sectors > max_crypt_sectors)
> +		crypt->total_sectors = max_crypt_sectors;
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
> +				 " sectors, skipping\n",
> +				 segment.slot_key);
> +	  continue;
> +	}
> +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
> +				 " data position greater than source disk size,"
> +				 " the end of the crypto device will be"
> +				 " inaccessible\n",
> +				 segment.slot_key);
> +	  /* Allow decryption up to the end of the source disk. */
> +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
> +	}
>
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index 132a1bb75..1a9e8fcf4 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -174,6 +174,22 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
>  /* Return value of grub_disk_get_size() in case disk size is unknown. */
>  #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
>
> +/* Convert sector number from disk sized sectors to a log-size sized sector. */
> +static inline grub_disk_addr_t
> +grub_disk_convert_sector (grub_disk_t disk,
> +			  grub_disk_addr_t sector,
> +			  grub_size_t log_sector_size)
> +{
> +  if (disk->log_sector_size < log_sector_size)
> +    {
> +      /* Round up to the nearest log_sector_size sized sector. */
> +      sector += 1ULL << ((log_sector_size / disk->log_sector_size) - 1);

ALIGN_UP()?

> +      return sector >> (log_sector_size - disk->log_sector_size);
> +    }
> +  else
> +    return sector << (disk->log_sector_size - log_sector_size);
> +}
> +
>  /* Convert to GRUB native disk sized sector from disk sized sector. */
>  static inline grub_disk_addr_t
>  grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)

Daniel


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

* Re: [PATCH v6 08/12] luks2: Error check segment.sector_size
  2020-11-27  9:03           ` [PATCH v6 08/12] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-12-03 13:52             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 13:52 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:40AM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 09/12] whitespace: convert 8 spaces to tabs.
  2020-11-27  9:03           ` [PATCH v6 09/12] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-12-03 13:53             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 13:53 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:41AM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 10/12] mips: Enable __clzdi2()
  2020-11-27  9:03           ` [PATCH v6 10/12] mips: Enable __clzdi2() Glenn Washburn
@ 2020-12-03 14:00             ` Daniel Kiper
  2020-12-03 15:58               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 14:00 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:42AM -0600, Glenn Washburn wrote:
> This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
> __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
> enabled.
>
> Signed-off-by: Daniel Kiper <dkiper@net-space.pl>

This should be replaced with:

  Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
  Signed-off-by: Glenn Washburn <development@efficientek.com>

In general if somebody suggests you something and you use they idea then
you should use Suggested-by instead of SOB.

Anyway, I can fix it before committing the patch if you are OK with me
adding your SOB.

Daniel


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

* Re: [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-11-27  9:03           ` [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-12-03 14:02             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 14:02 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:43AM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-11-27  9:03           ` [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
@ 2020-12-03 14:13             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-03 14:13 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Nov 27, 2020 at 03:03:44AM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v6 10/12] mips: Enable __clzdi2()
  2020-12-03 14:00             ` Daniel Kiper
@ 2020-12-03 15:58               ` Glenn Washburn
  2020-12-04 13:07                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03 15:58 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Thu, 3 Dec 2020 15:00:14 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:42AM -0600, Glenn Washburn wrote:
> > This patch is similiar to commit 9dab2f51e (sparc: Enable
> > __clzsi2() and __clzdi2()) but for MIPS target and __clzdi2 only,
> > __clzsi2 was already enabled.
> >
> > Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
> 
> This should be replaced with:
> 
>   Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
>   Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> In general if somebody suggests you something and you use they idea
> then you should use Suggested-by instead of SOB.
> 
> Anyway, I can fix it before committing the patch if you are OK with me
> adding your SOB.

Sure, I'm fine with you adding my SOB. I don't know if you're not
taking finished patches that come after unfinished patches, so I was
just going to fix and include in my next iteration.  If you're ready to
take these patches, then go ahead and I'll have less patches in the v7
series.

Glenn


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

* Re: [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk
  2020-12-03 13:31             ` Daniel Kiper
@ 2020-12-03 16:24               ` Glenn Washburn
  2020-12-04 13:19                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03 16:24 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Thu, 3 Dec 2020 14:31:49 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Nov 27, 2020 at 03:03:39AM -0600, Glenn Washburn wrote:
> > First, check to make sure that source disk has a known size. If
> > not, print debug message and return error. There are 4 cases where
> > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > uboot), and in all those cases processing continues. So this is
> > probably a bit conservative. However, 3 of the cases seem
> > pathological, and the other, biosdisk, happens when booting from a
> > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > case, we'll error until someone complains.
> >
> > Do some sanity checking on data coming from the luks header. If
> > segment.size is "dynamic",
> >
> > Check for errors from grub_strtoull when converting segment size
> > from string. If a GRUB_ERR_BAD_NUMBER error was returned, then the
> > string was not a valid parsable number, so skip the key. If
> > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow in
> > converting to a 64-bit unsigned integer. So this could be a very
> > large disk (perhaps large raid array). In this case, we want to
> > continue to try to use this key so long as the source disk's size
> > is greater than this segment size. Otherwise, this is an invalid
> > segment, and continue on to the next key.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 80
> > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h    |
> > 16 +++++++++ 2 files changed, 93 insertions(+), 3 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index b7ed0642e..01f9608e5 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
> >        goto err;
> >      }
> >
> > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > +    {
> > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > in read. */
> > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > +			     "conservatively returning error\n",
> > source->name);
> > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > source device");
> > +      goto err;
> > +    }
> > +
> >    /* Try all keyslot */
> >    for (i = 0; i < size; i++)
> >      {
> > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > +
> > +      grub_errno = GRUB_ERR_NONE;
> >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > i); if (ret)
> >  	goto err;
> > +      if (grub_errno != GRUB_ERR_NONE)
> > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> > luks2_get_keyslot\n", grub_errno);
> >
> >        if (keyslot.priority == 0)
> >  	{
> > @@ -616,11 +630,71 @@ luks2_recover_key (grub_disk_t source,
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > (unsigned int) * 8
> >  		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1;
> > +      /* Set to the source disk size, which is the maximum we
> > allow. */
> > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > +
> > source->total_sectors,
> > +
> > crypt->log_sector_size); +
> > +      if (max_crypt_sectors < crypt->offset_sectors)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has offset"
> > +				 " %"PRIuGRUB_UINT64_T" which is
> > greater than"
> > +				 " source disk size
> > %"PRIuGRUB_UINT64_T","
> > +				 " skipping\n",
> > +				 segment.slot_key,
> > crypt->offset_sectors,
> > +				 max_crypt_sectors);
> > +	  continue;
> > +	}
> > +
> >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> > -			       - crypt->offset_sectors;
> > +	crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors; else
> > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size;
> > +	{
> > +	  grub_errno = GRUB_ERR_NONE;
> > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > NULL, 10) >> crypt->log_sector_size;
> 
> I think ">>" should not happen here...

Do you think this because ">>" should not operate on a value returned
by a call to grub_strtoull that has errored?  I don't think there's any
problem because the return value is a number, so there's no harm in
using ">>" on a garbage number to get another garbage number, as long
as we don't use the value. (Its also not technically a garbage number,
just one of two values in the error case)

Also I didn't want to set total_sectors to grub_strtoull because it
could be a little confusing since the return value of grub_strtoull is
bytes not sectors.  And yet storing in total_sectors.  I could use a
local variable, but was wanting to avoid that.  But I'm fine with this
suggestion.

> > +	  if (grub_errno == GRUB_ERR_NONE)
> > +	    ;
> 
> It should happen here... Or to be exact...
>   crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 <<
> crypt->log_sector_size); // Am I right? crypt->total_sectors >>=
> crypt->log_sector_size;

I don't think we need to decrypt partial blocks at the end.
Cryptsetup/dm-crypt enforces disk sizes that are multiples of the
sector size.  So if the size is not a multiple of blocksize, there's a
bug somewhere in cryptsetup/dm-crypt, and we don't need to deal with
the partial block.  At worse the use loses access to a partial block at
the end that they should never have had access to in the first place.

> > +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> 
> Missing space before "("...

Ack.

> > +	    {
> > +	      /* TODO: Unparsable number-string, try to use the
> > whole disk */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " \"%s\" is not a parsable
> > number\n",
> > +				     segment.slot_key,
> > segment.size);
> 
>   crypt->total_sectors = max_crypt_sectors; ?

Sure, I didn't think you'd want this since it potentially entails
trying to read past the end of the luks data, and thus getting
random data, which might crash (buggy) filesystem read code.
 
> > +	      continue;
> 
> ...and then drop continue?
>
> > +	    }
> > +	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > +	    {
> > +	      /*
> > +	       * There was an overflow in parsing segment.size, so
> > disk must
> > +	       * be very large or the string is incorrect.
> > +	       */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " %s overflowed 64-bit
> > unsigned integer,"
> > +				     " the end of the crypto
> > device will be"
> > +				     " inaccessible\n",
> > +				     segment.slot_key,
> > segment.size);
> > +	      if (crypt->total_sectors > max_crypt_sectors)
> > +		crypt->total_sectors = max_crypt_sectors;
> > +	    }
> > +	}
> > +
> > +      if (crypt->total_sectors == 0)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has zero"
> > +				 " sectors, skipping\n",
> > +				 segment.slot_key);
> > +	  continue;
> > +	}
> > +      else if (max_crypt_sectors < (crypt->offset_sectors +
> > crypt->total_sectors))
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has last"
> > +				 " data position greater than
> > source disk size,"
> > +				 " the end of the crypto device
> > will be"
> > +				 " inaccessible\n",
> > +				 segment.slot_key);
> > +	  /* Allow decryption up to the end of the source disk. */
> > +	  crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors;
> > +	}
> >
> >        ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); diff --git a/include/grub/disk.h
> > b/include/grub/disk.h index 132a1bb75..1a9e8fcf4 100644
> > --- a/include/grub/disk.h
> > +++ b/include/grub/disk.h
> > @@ -174,6 +174,22 @@ typedef struct grub_disk_memberlist
> > *grub_disk_memberlist_t; /* Return value of grub_disk_get_size() in
> > case disk size is unknown. */ #define GRUB_DISK_SIZE_UNKNOWN
> >  0xffffffffffffffffULL
> >
> > +/* Convert sector number from disk sized sectors to a log-size
> > sized sector. */ +static inline grub_disk_addr_t
> > +grub_disk_convert_sector (grub_disk_t disk,
> > +			  grub_disk_addr_t sector,
> > +			  grub_size_t log_sector_size)
> > +{
> > +  if (disk->log_sector_size < log_sector_size)
> > +    {
> > +      /* Round up to the nearest log_sector_size sized sector. */
> > +      sector += 1ULL << ((log_sector_size / disk->log_sector_size)
> > - 1);
> 
> ALIGN_UP()?

Sure, I can do that and then remove the comment.

> > +      return sector >> (log_sector_size - disk->log_sector_size);
> > +    }
> > +  else
> > +    return sector << (disk->log_sector_size - log_sector_size);
> > +}
> > +
> >  /* Convert to GRUB native disk sized sector from disk sized
> > sector. */ static inline grub_disk_addr_t
> >  grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t
> > sector)
> 
> Daniel


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

* Re: [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-03 12:35                 ` Daniel Kiper
@ 2020-12-03 16:46                   ` Glenn Washburn
  2020-12-04 13:23                     ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-03 16:46 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Thu, 3 Dec 2020 13:35:28 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Thu, Dec 03, 2020 at 01:23:17AM -0600, Glenn Washburn wrote:
> > On Wed, 2 Dec 2020 18:01:47 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Fri, Nov 27, 2020 at 03:03:33AM -0600, Glenn Washburn wrote:
> > > > This allows code using these structs to know the named key
> > > > associated with these json data structures. In the future we can
> > > > use these to provide better error messages to the user.
> > > >
> > > > Get rid of idx variable in luks2_get_keyslot which was
> > > > overloaded to be used
> > >
> > > I prefer if you add "()" to the function names, i.e.
> > > luks2_get_keyslot(), in the comments and commit messages. This
> > > way it is easier to understand what you mean.
> >
> > Ok.
> >
> > > > for both keyslot and segment slot keys.
> > > >
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > ---
> > > >  grub-core/disk/luks2.c | 13 ++++++++-----
> > > >  1 file changed, 8 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > index d96764a02..ab2c31dcd 100644
> > > > --- a/grub-core/disk/luks2.c
> > > > +++ b/grub-core/disk/luks2.c
> > > > @@ -65,6 +65,7 @@ typedef struct grub_luks2_header
> > > > grub_luks2_header_t;
> > > >
> > > >  struct grub_luks2_keyslot
> > > >  {
> > > > +  grub_uint64_t slot_key;
> > >
> > > Could you be more consistent and use keyslot instead of slot_key
> > > here?
> >
> > I intentionally chose not to use keyslot because I thought it was
> > confusing.  slot_key is not a keyslot in the sense of a slot for a
> > cryptographic key or key material as in the usage keyslot in the
> > struct named "grub_luks2_keyslot".  Its the key value of a "slot"
> > in a json associative array which is modeling a sparse array.
> > Perhaps just "key" might be more to your liking?
> 
> IMO "key" is more confusing in this context and it would require at
> least a comment to clarify what it means. Is not json_slot_key better
> then? Probably with some comment what is it too...

Yeah, that's a better name in terms of its descriptive power, but feels
kinda long.  I'm fine with using that though, and will use that for the
next patch series, unless I hear otherwise.

> > > >    grub_int64_t key_size;
> > > >    grub_int64_t priority;
> > > >    struct
> > > > @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot
> > > > grub_luks2_keyslot_t;
> > > >
> > > >  struct grub_luks2_segment
> > > >  {
> > > > +  grub_uint64_t slot_key;
> > >
> > > Ditto. The code below uses keyslot instead...
> > >
> > > >    grub_uint64_t offset;
> > > >    const char	*size;
> > > >    const char	*encryption;
> > > > @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment
> > > > grub_luks2_segment_t;
> > > >
> > > >  struct grub_luks2_digest
> > > >  {
> > > > +  grub_uint64_t slot_key;
> > > >    /* Both keyslots and segments are interpreted as bitfields
> > > > here */ grub_uint64_t	keyslots;
> > > >    grub_uint64_t	segments;
> > > > @@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t
> > > > *k, grub_luks2_digest_t *d, grub_luks2_s {
> > > >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > > > segment; grub_size_t i, size;
> > > > -  grub_uint64_t idx;
> > > >
> > > >    /* Get nth keyslot */
> > > >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> > > >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > > > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > > > +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
> 
> Should not keyslot be renamed to json_slot_key too?

If I understand you correctly, you're asking about the variable keyslot
of type grub_json_t.  Here keyslot is a json object representing a
keyslot (ie collection of parameters used to decrypt an encrypted key).
It is not what I call a "slot key", which is the value of a key in a
json associative array.  So keyslot is a json object, where as a slot
key is always a json string (afaik).  I believe that it is currently
appropriately named.

Glenn


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

* Re: [PATCH v6 10/12] mips: Enable __clzdi2()
  2020-12-03 15:58               ` Glenn Washburn
@ 2020-12-04 13:07                 ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-04 13:07 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 09:58:40AM -0600, Glenn Washburn wrote:
> On Thu, 3 Dec 2020 15:00:14 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:42AM -0600, Glenn Washburn wrote:
> > > This patch is similiar to commit 9dab2f51e (sparc: Enable
> > > __clzsi2() and __clzdi2()) but for MIPS target and __clzdi2 only,
> > > __clzsi2 was already enabled.
> > >
> > > Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
> >
> > This should be replaced with:
> >
> >   Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
> >   Signed-off-by: Glenn Washburn <development@efficientek.com>
> >
> > In general if somebody suggests you something and you use they idea
> > then you should use Suggested-by instead of SOB.
> >
> > Anyway, I can fix it before committing the patch if you are OK with me
> > adding your SOB.
>
> Sure, I'm fine with you adding my SOB. I don't know if you're not
> taking finished patches that come after unfinished patches, so I was
> just going to fix and include in my next iteration.  If you're ready to
> take these patches, then go ahead and I'll have less patches in the v7
> series.

Usually I try to take the patches which got my RB. I am going to take
your patches together with many others next week. If you want to repost
v7 before that go ahead. Just add my RB to the patches which got one.

Daniel


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

* Re: [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk
  2020-12-03 16:24               ` Glenn Washburn
@ 2020-12-04 13:19                 ` Daniel Kiper
  2020-12-04 14:51                   ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-04 13:19 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 10:24:46AM -0600, Glenn Washburn wrote:
> On Thu, 3 Dec 2020 14:31:49 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Fri, Nov 27, 2020 at 03:03:39AM -0600, Glenn Washburn wrote:
> > > First, check to make sure that source disk has a known size. If
> > > not, print debug message and return error. There are 4 cases where
> > > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > > uboot), and in all those cases processing continues. So this is
> > > probably a bit conservative. However, 3 of the cases seem
> > > pathological, and the other, biosdisk, happens when booting from a
> > > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > > case, we'll error until someone complains.
> > >
> > > Do some sanity checking on data coming from the luks header. If
> > > segment.size is "dynamic",
> > >
> > > Check for errors from grub_strtoull when converting segment size
> > > from string. If a GRUB_ERR_BAD_NUMBER error was returned, then the
> > > string was not a valid parsable number, so skip the key. If
> > > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow in
> > > converting to a 64-bit unsigned integer. So this could be a very
> > > large disk (perhaps large raid array). In this case, we want to
> > > continue to try to use this key so long as the source disk's size
> > > is greater than this segment size. Otherwise, this is an invalid
> > > segment, and continue on to the next key.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 80
> > > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h    |
> > > 16 +++++++++ 2 files changed, 93 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index b7ed0642e..01f9608e5 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
> > >        goto err;
> > >      }
> > >
> > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > +    {
> > > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > > in read. */
> > > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > > +			     "conservatively returning error\n",
> > > source->name);
> > > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > > source device");
> > > +      goto err;
> > > +    }
> > > +
> > >    /* Try all keyslot */
> > >    for (i = 0; i < size; i++)
> > >      {
> > > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > > +
> > > +      grub_errno = GRUB_ERR_NONE;
> > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > > i); if (ret)
> > >  	goto err;
> > > +      if (grub_errno != GRUB_ERR_NONE)
> > > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> > > luks2_get_keyslot\n", grub_errno);
> > >
> > >        if (keyslot.priority == 0)
> > >  	{
> > > @@ -616,11 +630,71 @@ luks2_recover_key (grub_disk_t source,
> > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > > (unsigned int) * 8
> > >  		- __builtin_clz ((unsigned int)
> > > segment.sector_size) - 1;
> > > +      /* Set to the source disk size, which is the maximum we
> > > allow. */
> > > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > > +
> > > source->total_sectors,
> > > +
> > > crypt->log_sector_size); +
> > > +      if (max_crypt_sectors < crypt->offset_sectors)
> > > +	{
> > > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > > has offset"
> > > +				 " %"PRIuGRUB_UINT64_T" which is
> > > greater than"
> > > +				 " source disk size
> > > %"PRIuGRUB_UINT64_T","
> > > +				 " skipping\n",
> > > +				 segment.slot_key,
> > > crypt->offset_sectors,
> > > +				 max_crypt_sectors);
> > > +	  continue;
> > > +	}
> > > +
> > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > (crypt->log_sector_size - source->log_sector_size))
> > > -			       - crypt->offset_sectors;
> > > +	crypt->total_sectors = max_crypt_sectors -
> > > crypt->offset_sectors; else
> > > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > > 10) >> crypt->log_sector_size;
> > > +	{
> > > +	  grub_errno = GRUB_ERR_NONE;
> > > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > > NULL, 10) >> crypt->log_sector_size;
> >
> > I think ">>" should not happen here...
>
> Do you think this because ">>" should not operate on a value returned
> by a call to grub_strtoull that has errored?  I don't think there's any
> problem because the return value is a number, so there's no harm in
> using ">>" on a garbage number to get another garbage number, as long
> as we don't use the value. (Its also not technically a garbage number,
> just one of two values in the error case)
>
> Also I didn't want to set total_sectors to grub_strtoull because it
> could be a little confusing since the return value of grub_strtoull is
> bytes not sectors.  And yet storing in total_sectors.  I could use a
> local variable, but was wanting to avoid that.  But I'm fine with this
> suggestion.

OK, let's leave it as it is...

> > > +	  if (grub_errno == GRUB_ERR_NONE)
> > > +	    ;
> >
> > It should happen here... Or to be exact...
> >   crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 <<
> > crypt->log_sector_size); // Am I right? crypt->total_sectors >>=
> > crypt->log_sector_size;
>
> I don't think we need to decrypt partial blocks at the end.
> Cryptsetup/dm-crypt enforces disk sizes that are multiples of the
> sector size.  So if the size is not a multiple of blocksize, there's a
> bug somewhere in cryptsetup/dm-crypt, and we don't need to deal with
> the partial block.  At worse the use loses access to a partial block at
> the end that they should never have had access to in the first place.

Does GRUB fail safely in such cases?

> > > +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> >
> > Missing space before "("...
>
> Ack.
>
> > > +	    {
> > > +	      /* TODO: Unparsable number-string, try to use the
> > > whole disk */
> > > +	      grub_dprintf ("luks2", "Segment
> > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > +				     " \"%s\" is not a parsable
> > > number\n",
> > > +				     segment.slot_key,
> > > segment.size);
> >
> >   crypt->total_sectors = max_crypt_sectors; ?
>
> Sure, I didn't think you'd want this since it potentially entails
> trying to read past the end of the luks data, and thus getting
> random data, which might crash (buggy) filesystem read code.

OK but then I would drop "TODO" comment because we do not want to
make this case work...

Daniel


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

* Re: [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-03 16:46                   ` Glenn Washburn
@ 2020-12-04 13:23                     ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-04 13:23 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Thu, Dec 03, 2020 at 10:46:12AM -0600, Glenn Washburn wrote:
> On Thu, 3 Dec 2020 13:35:28 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Thu, Dec 03, 2020 at 01:23:17AM -0600, Glenn Washburn wrote:
> > > On Wed, 2 Dec 2020 18:01:47 +0100
> > > Daniel Kiper <dkiper@net-space.pl> wrote:
> > >
> > > > On Fri, Nov 27, 2020 at 03:03:33AM -0600, Glenn Washburn wrote:
> > > > > This allows code using these structs to know the named key
> > > > > associated with these json data structures. In the future we can
> > > > > use these to provide better error messages to the user.
> > > > >
> > > > > Get rid of idx variable in luks2_get_keyslot which was
> > > > > overloaded to be used
> > > >
> > > > I prefer if you add "()" to the function names, i.e.
> > > > luks2_get_keyslot(), in the comments and commit messages. This
> > > > way it is easier to understand what you mean.
> > >
> > > Ok.
> > >
> > > > > for both keyslot and segment slot keys.
> > > > >
> > > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > > ---
> > > > >  grub-core/disk/luks2.c | 13 ++++++++-----
> > > > >  1 file changed, 8 insertions(+), 5 deletions(-)
> > > > >
> > > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > > index d96764a02..ab2c31dcd 100644
> > > > > --- a/grub-core/disk/luks2.c
> > > > > +++ b/grub-core/disk/luks2.c
> > > > > @@ -65,6 +65,7 @@ typedef struct grub_luks2_header
> > > > > grub_luks2_header_t;
> > > > >
> > > > >  struct grub_luks2_keyslot
> > > > >  {
> > > > > +  grub_uint64_t slot_key;
> > > >
> > > > Could you be more consistent and use keyslot instead of slot_key
> > > > here?
> > >
> > > I intentionally chose not to use keyslot because I thought it was
> > > confusing.  slot_key is not a keyslot in the sense of a slot for a
> > > cryptographic key or key material as in the usage keyslot in the
> > > struct named "grub_luks2_keyslot".  Its the key value of a "slot"
> > > in a json associative array which is modeling a sparse array.
> > > Perhaps just "key" might be more to your liking?
> >
> > IMO "key" is more confusing in this context and it would require at
> > least a comment to clarify what it means. Is not json_slot_key better
> > then? Probably with some comment what is it too...
>
> Yeah, that's a better name in terms of its descriptive power, but feels
> kinda long.  I'm fine with using that though, and will use that for the
> next patch series, unless I hear otherwise.

Yeah, unfortunately world is not perfect... :-(

> > > > >    grub_int64_t key_size;
> > > > >    grub_int64_t priority;
> > > > >    struct
> > > > > @@ -103,6 +104,7 @@ typedef struct grub_luks2_keyslot
> > > > > grub_luks2_keyslot_t;
> > > > >
> > > > >  struct grub_luks2_segment
> > > > >  {
> > > > > +  grub_uint64_t slot_key;
> > > >
> > > > Ditto. The code below uses keyslot instead...
> > > >
> > > > >    grub_uint64_t offset;
> > > > >    const char	*size;
> > > > >    const char	*encryption;
> > > > > @@ -112,6 +114,7 @@ typedef struct grub_luks2_segment
> > > > > grub_luks2_segment_t;
> > > > >
> > > > >  struct grub_luks2_digest
> > > > >  {
> > > > > +  grub_uint64_t slot_key;
> > > > >    /* Both keyslots and segments are interpreted as bitfields
> > > > > here */ grub_uint64_t	keyslots;
> > > > >    grub_uint64_t	segments;
> > > > > @@ -259,12 +262,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t
> > > > > *k, grub_luks2_digest_t *d, grub_luks2_s {
> > > > >    grub_json_t keyslots, keyslot, digests, digest, segments,
> > > > > segment; grub_size_t i, size;
> > > > > -  grub_uint64_t idx;
> > > > >
> > > > >    /* Get nth keyslot */
> > > > >    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> > > > >        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> > > > > -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> > > > > +      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
> >
> > Should not keyslot be renamed to json_slot_key too?
>
> If I understand you correctly, you're asking about the variable keyslot
> of type grub_json_t.  Here keyslot is a json object representing a
> keyslot (ie collection of parameters used to decrypt an encrypted key).
> It is not what I call a "slot key", which is the value of a key in a
> json associative array.  So keyslot is a json object, where as a slot
> key is always a json string (afaik).  I believe that it is currently
> appropriately named.

OK, so, leave it as it is right now.

Daniel


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

* Re: [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk
  2020-12-04 13:19                 ` Daniel Kiper
@ 2020-12-04 14:51                   ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 14:51 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Fri, 4 Dec 2020 14:19:29 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Thu, Dec 03, 2020 at 10:24:46AM -0600, Glenn Washburn wrote:
> > On Thu, 3 Dec 2020 14:31:49 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Fri, Nov 27, 2020 at 03:03:39AM -0600, Glenn Washburn wrote:
> > > > First, check to make sure that source disk has a known size. If
> > > > not, print debug message and return error. There are 4 cases
> > > > where GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk,
> > > > and uboot), and in all those cases processing continues. So
> > > > this is probably a bit conservative. However, 3 of the cases
> > > > seem pathological, and the other, biosdisk, happens when
> > > > booting from a cd. Since I doubt booting from a LUKS2 volume on
> > > > a cd is a big use case, we'll error until someone complains.
> > > >
> > > > Do some sanity checking on data coming from the luks header. If
> > > > segment.size is "dynamic",
> > > >
> > > > Check for errors from grub_strtoull when converting segment size
> > > > from string. If a GRUB_ERR_BAD_NUMBER error was returned, then
> > > > the string was not a valid parsable number, so skip the key. If
> > > > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow
> > > > in converting to a 64-bit unsigned integer. So this could be a
> > > > very large disk (perhaps large raid array). In this case, we
> > > > want to continue to try to use this key so long as the source
> > > > disk's size is greater than this segment size. Otherwise, this
> > > > is an invalid segment, and continue on to the next key.
> > > >
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > ---
> > > >  grub-core/disk/luks2.c | 80
> > > > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h
> > > >   | 16 +++++++++ 2 files changed, 93 insertions(+), 3
> > > > deletions(-)
> > > >
> > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > index b7ed0642e..01f9608e5 100644
> > > > --- a/grub-core/disk/luks2.c
> > > > +++ b/grub-core/disk/luks2.c
> > > > @@ -597,12 +597,26 @@ luks2_recover_key (grub_disk_t source,
> > > >        goto err;
> > > >      }
> > > >
> > > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > > +    {
> > > > +      /* FIXME: Allow use of source disk, and maybe cause
> > > > errors in read. */
> > > > +      grub_dprintf ("luks2", "Source disk %s has an unknown
> > > > size, "
> > > > +			     "conservatively returning
> > > > error\n", source->name);
> > > > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > > > source device");
> > > > +      goto err;
> > > > +    }
> > > > +
> > > >    /* Try all keyslot */
> > > >    for (i = 0; i < size; i++)
> > > >      {
> > > > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > > > +
> > > > +      grub_errno = GRUB_ERR_NONE;
> > > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment,
> > > > json, i); if (ret)
> > > >  	goto err;
> > > > +      if (grub_errno != GRUB_ERR_NONE)
> > > > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d
> > > > from luks2_get_keyslot\n", grub_errno);
> > > >
> > > >        if (keyslot.priority == 0)
> > > >  	{
> > > > @@ -616,11 +630,71 @@ luks2_recover_key (grub_disk_t source,
> > > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > > > (unsigned int) * 8
> > > >  		- __builtin_clz ((unsigned int)
> > > > segment.sector_size) - 1;
> > > > +      /* Set to the source disk size, which is the maximum we
> > > > allow. */
> > > > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > > > +
> > > > source->total_sectors,
> > > > +
> > > > crypt->log_sector_size); +
> > > > +      if (max_crypt_sectors < crypt->offset_sectors)
> > > > +	{
> > > > +	  grub_dprintf ("luks2", "Segment
> > > > \"%"PRIuGRUB_UINT64_T"\" has offset"
> > > > +				 " %"PRIuGRUB_UINT64_T" which
> > > > is greater than"
> > > > +				 " source disk size
> > > > %"PRIuGRUB_UINT64_T","
> > > > +				 " skipping\n",
> > > > +				 segment.slot_key,
> > > > crypt->offset_sectors,
> > > > +				 max_crypt_sectors);
> > > > +	  continue;
> > > > +	}
> > > > +
> > > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > > (crypt->log_sector_size - source->log_sector_size))
> > > > -			       - crypt->offset_sectors;
> > > > +	crypt->total_sectors = max_crypt_sectors -
> > > > crypt->offset_sectors; else
> > > > -	crypt->total_sectors = grub_strtoull (segment.size,
> > > > NULL, 10) >> crypt->log_sector_size;
> > > > +	{
> > > > +	  grub_errno = GRUB_ERR_NONE;
> > > > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > > > NULL, 10) >> crypt->log_sector_size;
> > >
> > > I think ">>" should not happen here...
> >
> > Do you think this because ">>" should not operate on a value
> > returned by a call to grub_strtoull that has errored?  I don't
> > think there's any problem because the return value is a number, so
> > there's no harm in using ">>" on a garbage number to get another
> > garbage number, as long as we don't use the value. (Its also not
> > technically a garbage number, just one of two values in the error
> > case)
> >
> > Also I didn't want to set total_sectors to grub_strtoull because it
> > could be a little confusing since the return value of grub_strtoull
> > is bytes not sectors.  And yet storing in total_sectors.  I could
> > use a local variable, but was wanting to avoid that.  But I'm fine
> > with this suggestion.
> 
> OK, let's leave it as it is...
> 
> > > > +	  if (grub_errno == GRUB_ERR_NONE)
> > > > +	    ;
> > >
> > > It should happen here... Or to be exact...
> > >   crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 <<
> > > crypt->log_sector_size); // Am I right? crypt->total_sectors >>=
> > > crypt->log_sector_size;
> >
> > I don't think we need to decrypt partial blocks at the end.
> > Cryptsetup/dm-crypt enforces disk sizes that are multiples of the
> > sector size.  So if the size is not a multiple of blocksize,
> > there's a bug somewhere in cryptsetup/dm-crypt, and we don't need
> > to deal with the partial block.  At worse the use loses access to a
> > partial block at the end that they should never have had access to
> > in the first place.
> 
> Does GRUB fail safely in such cases?

I think the question boils down to the filesystem driver code. On
second thought, I'll take the suggestion to round up to nearest sector.

> > > > +	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
> > >
> > > Missing space before "("...
> >
> > Ack.
> >
> > > > +	    {
> > > > +	      /* TODO: Unparsable number-string, try to use the
> > > > whole disk */
> > > > +	      grub_dprintf ("luks2", "Segment
> > > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > > +				     " \"%s\" is not a parsable
> > > > number\n",
> > > > +				     segment.slot_key,
> > > > segment.size);
> > >
> > >   crypt->total_sectors = max_crypt_sectors; ?
> >
> > Sure, I didn't think you'd want this since it potentially entails
> > trying to read past the end of the luks data, and thus getting
> > random data, which might crash (buggy) filesystem read code.
> 
> OK but then I would drop "TODO" comment because we do not want to
> make this case work...

Ideally I think we do want to make this case work, which would entail
being confident enough that the file system code won't horribly break.
We may actually be at that point, I just don't know the various
filesystem drivers well enough to know either way.  If we had a setup to
run a filesystem fuzzer over it that might help confidence levels.

Since I think its pretty improbable that there's an unparsable
segment.size but we can get all other needed params to unlock the
drive, I'll drop the todo.

Glenn


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

* [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (17 preceding siblings ...)
  2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-12-04 16:43         ` Glenn Washburn
  2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
                             ` (17 more replies)
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
  19 siblings, 18 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch series is an update to reflect changes suggested in v6. Of note,
there are a few new patches: 01, 02, and 04.

  01: Daniel suggested to renae grub_disk_get_size to grub_disk_native_sectors
  02: Make ALIGN_UP and ALIGN_DOWN safer
  04: Make luks2_parse_digest() safer

Glenn

Glenn Washburn (17):
  disk: Rename grub_disk_get_size to grub_disk_native_sectors
  misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  luks2: Remove unused argument in grub_error
  luks2: Make sure all fields of output argument in luks2_parse_digest()
    are written to
  luks2: Add json_slot_key member to struct
    grub_luks2_keyslot/segment/digest
  luks2: Use more intuitive slot key instead of index in user messages
  luks2: Add string "index" to user strings using a json index.
  cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  luks2: grub_cryptodisk_t->total_sectors is the max number of device
    native sectors
  cryptodisk: Properly handle non-512 byte sized sectors
  luks2: Better error handling when setting up the cryptodisk
  luks2: Error check segment.sector_size
  whitespace: convert 8 spaces to tabs
  mips: Enable __clzdi2()
  misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
    integers
  luks2: Use grub_log2ull to calculate log_sector_size and improve
    readability

 grub-core/disk/cryptodisk.c        |  64 +++++++-----
 grub-core/disk/diskfilter.c        |  12 +--
 grub-core/disk/dmraid_nvidia.c     |   2 +-
 grub-core/disk/efi/efidisk.c       |   2 +-
 grub-core/disk/geli.c              |   6 +-
 grub-core/disk/ldm.c               |   4 +-
 grub-core/disk/luks.c              |   7 +-
 grub-core/disk/luks2.c             | 160 +++++++++++++++++++++++------
 grub-core/disk/mdraid1x_linux.c    |   2 +-
 grub-core/disk/mdraid_linux.c      |   2 +-
 grub-core/fs/cbfs.c                |  16 +--
 grub-core/fs/nilfs2.c              |   2 +-
 grub-core/fs/zfs/zfs.c             |   4 +-
 grub-core/kern/compiler-rt.c       |   2 +-
 grub-core/kern/disk.c              |   2 +-
 grub-core/kern/mips/arc/init.c     |   2 +-
 grub-core/normal/misc.c            |   6 +-
 grub-core/osdep/windows/platform.c |   2 +-
 include/grub/compiler-rt.h         |   2 +-
 include/grub/cryptodisk.h          |   8 +-
 include/grub/disk.h                |  21 +++-
 include/grub/misc.h                |   7 +-
 include/grub/types.h               |   9 ++
 util/grub-install.c                |   2 +-
 util/grub-probe.c                  |   2 +-
 25 files changed, 249 insertions(+), 99 deletions(-)

Range-diff against v6:
 -:  --------- >  1:  7e79d6fb1 disk: Rename grub_disk_get_size to grub_disk_native_sectors
 -:  --------- >  2:  77f9671d5 misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
 3:  8527be145 !  3:  d1a36aa79 luks2: Remove unused argument in grub_error
    @@ Metadata
      ## Commit message ##
         luks2: Remove unused argument in grub_error
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
            grub_json_getstring (&out->size, segment, "size") ||
 -:  --------- >  4:  dab43e033 luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
 1:  6262aefe9 !  5:  35f47644c luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
    +    luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
     
         This allows code using these structs to know the named key associated with
         these json data structures. In the future we can use these to provide better
         error messages to the user.
     
    -    Get rid of idx variable in luks2_get_keyslot which was overloaded to be used
    -    for both keyslot and segment slot keys.
    +    Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
    +    used for both keyslot and segment slot keys.
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
      
      struct grub_luks2_keyslot
      {
    -+  grub_uint64_t slot_key;
    ++  /* The integer key to the associative array of keyslots */
    ++  grub_uint64_t json_slot_key;
        grub_int64_t key_size;
        grub_int64_t priority;
        struct
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
      
      struct grub_luks2_segment
      {
    -+  grub_uint64_t slot_key;
    ++  grub_uint64_t json_slot_key;
        grub_uint64_t offset;
        const char	*size;
        const char	*encryption;
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_segment grub_luks2_segment_t;
      
      struct grub_luks2_digest
      {
    -+  grub_uint64_t slot_key;
    ++  grub_uint64_t json_slot_key;
        /* Both keyslots and segments are interpreted as bitfields here */
        grub_uint64_t	keyslots;
        grub_uint64_t	segments;
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
        if (grub_json_getvalue (&keyslots, root, "keyslots") ||
            grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
     -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
    -+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
    ++      grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
            grub_json_getchild (&keyslot, &keyslot, 0) ||
            luks2_parse_keyslot (k, &keyslot))
          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
        for (i = 0; i < size; i++)
          {
            if (grub_json_getchild (&digest, &digests, i) ||
    -+	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
    ++	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
                grub_json_getchild (&digest, &digest, 0) ||
                luks2_parse_digest (d, &digest))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
      
     -      if ((d->keyslots & (1 << idx)))
    -+      if ((d->keyslots & (1 << k->slot_key)))
    ++      if ((d->keyslots & (1 << k->json_slot_key)))
      	break;
          }
        if (i == size)
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
          {
            if (grub_json_getchild (&segment, &segments, i) ||
     -	  grub_json_getuint64 (&idx, &segment, NULL) ||
    -+	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
    ++	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
      	  grub_json_getchild (&segment, &segment, 0) ||
                luks2_parse_segment (s, &segment))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
      
     -      if ((d->segments & (1 << idx)))
    -+      if ((d->segments & (1 << s->slot_key)))
    ++      if ((d->segments & (1 << s->json_slot_key)))
      	break;
          }
        if (i == size)
 2:  3cd52834b !  6:  e52887944 luks2: Use more intuitive slot key instead of index in user messages.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Use more intuitive slot key instead of index in user messages.
    +    luks2: Use more intuitive slot key instead of index in user messages
     
         Use the slot key name in the json array rather than the 0 based index in the
         json array for keyslots, segments, and digests. This is less confusing for
    @@ Commit message
         messages using the index of the keyslot will mention keyslot 1 (its a
         zero-based index). Furthermore, with this change the keyslot number will
         align with the number used to reference the keyslot when using the
    -    --key-slot argument to cryptsetup. Error messages now distinguish between
    -    indexes and slot keys. The former include the string "index" in the error
    -    string, and the later are surrounded in quotes.
    +    --key-slot argument to cryptsetup.
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    -       grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
    -       grub_json_getchild (&keyslot, &keyslot, 0) ||
    -       luks2_parse_keyslot (k, &keyslot))
    --    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
    -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
    - 
    -   /* Get digest that matches the keyslot. */
    -   if (grub_json_getvalue (&digests, root, "digests") ||
    -@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
    + 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
                grub_json_getchild (&digest, &digest, 0) ||
                luks2_parse_digest (d, &digest))
     -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
     +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
      
    -       if ((d->keyslots & (1 << k->slot_key)))
    +       if ((d->keyslots & (1 << k->json_slot_key)))
      	break;
          }
        if (i == size)
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
        /* Get segment that matches the digest. */
        if (grub_json_getvalue (&segments, root, "segments") ||
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
    - 	  grub_json_getchild (&segment, &segment, 0) ||
    -           luks2_parse_segment (s, &segment))
    --	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
    -+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
    - 
    -       if ((d->segments & (1 << s->slot_key)))
      	break;
          }
        if (i == size)
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            if (keyslot.priority == 0)
      	{
     -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
    -+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
    ++	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
      	  continue;
              }
      
     -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
    -+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
    ++      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
      
            /* Set up disk according to keyslot's segment. */
            crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      	{
     -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
     -			i, grub_errmsg);
    -+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
    ++	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
     +			keyslot.slot_key, grub_errmsg);
      	  continue;
      	}
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      	{
     -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
     -			i, grub_errmsg);
    -+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
    ++	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
     +			keyslot.slot_key, grub_errmsg);
      	  continue;
      	}
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
             * where each element is either empty or holds a key.
             */
     -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
    -+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
    ++      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
      
            candidate_key_len = keyslot.key_size;
            break;
 4:  1a248b679 <  -:  --------- cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
 -:  --------- >  7:  43e3b6cce luks2: Add string "index" to user strings using a json index.
 -:  --------- >  8:  4aa9757e1 cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
 -:  --------- >  9:  d18993a63 cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
 5:  45f5d644f ! 10:  7e8f242d1 luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
    @@ Commit message
     
         We need to convert the sectors from the size of the underlying device to the
         cryptodisk sector size; segment.size is in bytes which need to be converted
    -    to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
    -    returns the total number of device native sectors.
    +    to cryptodisk sectors as well.
     
         Also, removed an empty statement.
     
    -    Signed-off-by: Glenn Washburn <development@efficientek.com>
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_decrypt_key (grub_uint8_t *out_key,
 6:  6e01cafb1 ! 11:  1fe9c38ed cryptodisk: Properly handle non-512 byte sized sectors
    @@ Commit message
         512 (ie the IV increments every 512 bytes). This made these changes less
         aestetically pleasing than desired.
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +
      ## grub-core/disk/cryptodisk.c ##
     @@ grub-core/disk/cryptodisk.c: lrw_xor (const struct lrw_sector *sec,
      static gcry_err_code_t
    @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
      	  }
      	  break;
      	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
    --	  iv[1] = grub_cpu_to_le32 (sector >> 32);
    +-	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
     -	  /* FALLTHROUGH */
      	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
     -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
    @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
        newdev->source_disk = NULL;
     -  newdev->log_sector_size = 9;
     +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
    -   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
    +   newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
        grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
        newdev->modname = "luks";
     @@ grub-core/disk/luks.c: luks_recover_key (grub_disk_t source,
 7:  d8927c6bc ! 12:  c9db343e8 luks2: Better error handling when setting up the cryptodisk
    @@ Commit message
         an invalid segment, and continue on to the next key.
     
      ## grub-core/disk/luks2.c ##
    +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    + 	break;
    +     }
    +   if (i == size)
    +-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
    ++      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key);
    + 
    +   /* Get segment that matches the digest. */
    +   if (grub_json_getvalue (&segments, root, "segments") ||
    +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    + 	break;
    +     }
    +   if (i == size)
    +-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
    ++    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key);
    + 
    +   return GRUB_ERR_NONE;
    + }
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            goto err;
          }
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
            if (keyslot.priority == 0)
      	{
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    +-	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
    ++	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
    + 	  continue;
    +         }
    + 
    +-      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
    ++      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
    + 
    +       /* Set up disk according to keyslot's segment. */
            crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				 " %"PRIuGRUB_UINT64_T" which is greater than"
     +				 " source disk size %"PRIuGRUB_UINT64_T","
     +				 " skipping\n",
    -+				 segment.slot_key, crypt->offset_sectors,
    ++				 segment.json_slot_key, crypt->offset_sectors,
     +				 max_crypt_sectors);
     +	  continue;
     +	}
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
     +	{
     +	  grub_errno = GRUB_ERR_NONE;
    -+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
    ++	  /* Convert segment.size to sectors, rounding up to nearest sector */
    ++	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
    ++	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
    ++					   1 << crypt->log_sector_size);
    ++	  crypt->total_sectors >>= crypt->log_sector_size;
    ++
     +	  if (grub_errno == GRUB_ERR_NONE)
     +	    ;
    -+	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
    ++	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
     +	    {
    -+	      /* TODO: Unparsable number-string, try to use the whole disk */
     +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
     +				     " \"%s\" is not a parsable number\n",
    -+				     segment.slot_key, segment.size);
    ++				     segment.json_slot_key, segment.size);
     +	      continue;
     +	    }
    -+	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
    ++	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
     +	    {
     +	      /*
     +	       * There was an overflow in parsing segment.size, so disk must
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				     " %s overflowed 64-bit unsigned integer,"
     +				     " the end of the crypto device will be"
     +				     " inaccessible\n",
    -+				     segment.slot_key, segment.size);
    ++				     segment.json_slot_key, segment.size);
     +	      if (crypt->total_sectors > max_crypt_sectors)
     +		crypt->total_sectors = max_crypt_sectors;
     +	    }
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	{
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
     +				 " sectors, skipping\n",
    -+				 segment.slot_key);
    ++				 segment.json_slot_key);
     +	  continue;
     +	}
     +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				 " data position greater than source disk size,"
     +				 " the end of the crypto device will be"
     +				 " inaccessible\n",
    -+				 segment.slot_key);
    ++				 segment.json_slot_key);
     +	  /* Allow decryption up to the end of the source disk. */
     +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
     +	}
      
            ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
      			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
    +       if (ret)
    + 	{
    + 	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
    +-			keyslot.slot_key, grub_errmsg);
    ++			keyslot.json_slot_key, grub_errmsg);
    + 	  continue;
    + 	}
    + 
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    +       if (ret)
    + 	{
    + 	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
    +-			keyslot.slot_key, grub_errmsg);
    ++			keyslot.json_slot_key, grub_errmsg);
    + 	  continue;
    + 	}
    + 
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    +        * TRANSLATORS: It's a cryptographic key slot: one element of an array
    +        * where each element is either empty or holds a key.
    +        */
    +-      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
    ++      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.json_slot_key);
    + 
    +       candidate_key_len = keyslot.key_size;
    +       break;
     
      ## include/grub/disk.h ##
    +@@
    + #include <grub/device.h>
    + /* For NULL.  */
    + #include <grub/mm.h>
    ++/* For ALIGN_UP.  */
    ++#include <grub/misc.h>
    + 
    + /* These are used to set a device id. When you add a new disk device,
    +    you must define a new id for it here.  */
     @@ include/grub/disk.h: typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
    - /* Return value of grub_disk_get_size() in case disk size is unknown. */
    + /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
      #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
      
     +/* Convert sector number from disk sized sectors to a log-size sized sector. */
    @@ include/grub/disk.h: typedef struct grub_disk_memberlist *grub_disk_memberlist_t
     +{
     +  if (disk->log_sector_size < log_sector_size)
     +    {
    -+      /* Round up to the nearest log_sector_size sized sector. */
    -+      sector += 1ULL << ((log_sector_size / disk->log_sector_size) - 1);
    ++      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));
     +      return sector >> (log_sector_size - disk->log_sector_size);
     +    }
     +  else
 8:  fcd7aadb7 ! 13:  2fcef44b6 luks2: Error check segment.sector_size
    @@ Metadata
      ## Commit message ##
         luks2: Error check segment.sector_size
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
    -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
    +       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
      
     +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
     +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
     +				 " size %"PRIuGRUB_UINT64_T" is not one of"
     +				 " 512, 1024, 2048, or 4096\n",
    -+				 segment.slot_key, segment.sector_size);
    ++				 segment.json_slot_key, segment.sector_size);
     +	  continue;
     +	}
     +
 9:  61f77a1a8 ! 14:  74eed4a62 whitespace: convert 8 spaces to tabs.
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    whitespace: convert 8 spaces to tabs.
    +    whitespace: convert 8 spaces to tabs
    +
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
          {
            if (grub_json_getchild (&digest, &digests, i) ||
    - 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
    + 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
     -          grub_json_getchild (&digest, &digest, 0) ||
     -          luks2_parse_digest (d, &digest))
     +	  grub_json_getchild (&digest, &digest, 0) ||
     +	  luks2_parse_digest (d, &digest))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
      
    -       if ((d->keyslots & (1 << k->slot_key)))
    +       if ((d->keyslots & (1 << k->json_slot_key)))
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
            if (grub_json_getchild (&segment, &segments, i) ||
    - 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
    + 	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
      	  grub_json_getchild (&segment, &segment, 0) ||
     -          luks2_parse_segment (s, &segment))
     +	  luks2_parse_segment (s, &segment))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
      
    -       if ((d->segments & (1 << s->slot_key)))
    +       if ((d->segments & (1 << s->json_slot_key)))
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      	{
    - 	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
    + 	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
      	  continue;
     -        }
     +	}
      
    -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
    +       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
      
10:  d71d26701 ! 15:  51c2e9160 mips: Enable __clzdi2()
    @@ Commit message
         __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
         enabled.
     
    -    Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
    +    Suggested-by: Daniel Kiper <dkiper@net-space.pl>
     
      ## grub-core/kern/compiler-rt.c ##
     @@ grub-core/kern/compiler-rt.c: __clzsi2 (grub_uint32_t val)
11:  8aa295f77 ! 16:  3b4ccda1f misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
    @@ Metadata
      ## Commit message ##
         misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +
      ## include/grub/misc.h ##
     @@ include/grub/misc.h: void EXPORT_FUNC(grub_real_boot_time) (const char *file,
      #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
12:  7050a4ace ! 17:  8b97e6887 luks2: Use grub_log2ull to calculate log_sector_size and improve readability
    @@ Metadata
      ## Commit message ##
         luks2: Use grub_log2ull to calculate log_sector_size and improve readability
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
-- 
2.27.0



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

* [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:24             ` Patrick Steinhardt
  2020-12-07 19:38             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
                             ` (16 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

The function grub_disk_get_size is confusingly named because it actually
returns a sector count where the sectors are sized in the grub native sector
size. Rename to something more appropriate.

Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/diskfilter.c        | 12 ++++++------
 grub-core/disk/dmraid_nvidia.c     |  2 +-
 grub-core/disk/efi/efidisk.c       |  2 +-
 grub-core/disk/geli.c              |  6 +++---
 grub-core/disk/ldm.c               |  4 ++--
 grub-core/disk/luks.c              |  2 +-
 grub-core/disk/mdraid1x_linux.c    |  2 +-
 grub-core/disk/mdraid_linux.c      |  2 +-
 grub-core/fs/cbfs.c                | 16 ++++++++--------
 grub-core/fs/nilfs2.c              |  2 +-
 grub-core/fs/zfs/zfs.c             |  4 ++--
 grub-core/kern/disk.c              |  2 +-
 grub-core/kern/mips/arc/init.c     |  2 +-
 grub-core/normal/misc.c            |  6 +++---
 grub-core/osdep/windows/platform.c |  2 +-
 include/grub/disk.h                |  4 ++--
 util/grub-install.c                |  2 +-
 util/grub-probe.c                  |  2 +-
 18 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 86557f923..032011566 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -148,7 +148,7 @@ scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
 	if (m->disk && m->disk->id == disk->id
 	    && m->disk->dev->id == disk->dev->id
 	    && m->part_start == grub_partition_get_start (disk->partition)
-	    && m->part_size == grub_disk_get_size (disk))
+	    && m->part_size == grub_disk_native_sectors (disk))
 	  return 0;
     }
 
@@ -1190,13 +1190,13 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 
   grub_dprintf ("diskfilter", "Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name,
 		(unsigned long long) grub_partition_get_start (disk->partition),
-		(unsigned long long) grub_disk_get_size (disk),
+		(unsigned long long) grub_disk_native_sectors (disk),
 		array->name, diskfilter->name);
 #ifdef GRUB_UTIL
   grub_util_info ("Inserting %s (+%" GRUB_HOST_PRIuLONG_LONG ",%"
 		  GRUB_HOST_PRIuLONG_LONG ") into %s (%s)\n", disk->name,
 		  (unsigned long long) grub_partition_get_start (disk->partition),
-		  (unsigned long long) grub_disk_get_size (disk),
+		  (unsigned long long) grub_disk_native_sectors (disk),
 		  array->name, diskfilter->name);
   array->driver = diskfilter;
 #endif
@@ -1210,7 +1210,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 	struct grub_diskfilter_lv *lv;
 	/* FIXME: Check whether the update time of the superblocks are
 	   the same.  */
-	if (pv->disk && grub_disk_get_size (disk) >= pv->part_size)
+	if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size)
 	  return GRUB_ERR_NONE;
 	pv->disk = grub_disk_open (disk->name);
 	if (!pv->disk)
@@ -1219,7 +1219,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 	   raid device, we shouldn't change it.  */
 	pv->start_sector -= pv->part_start;
 	pv->part_start = grub_partition_get_start (disk->partition);
-	pv->part_size = grub_disk_get_size (disk);
+	pv->part_size = grub_disk_native_sectors (disk);
 
 #ifdef GRUB_UTIL
 	{
@@ -1311,7 +1311,7 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
 	if (pv->disk && pv->disk->id == disk->id
 	    && pv->disk->dev->id == disk->dev->id
 	    && pv->part_start == grub_partition_get_start (disk->partition)
-	    && pv->part_size == grub_disk_get_size (disk))
+	    && pv->part_size == grub_disk_native_sectors (disk))
 	  {
 	    if (vg_out)
 	      *vg_out = vg;
diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c
index 060279124..4d2fb04d1 100644
--- a/grub-core/disk/dmraid_nvidia.c
+++ b/grub-core/disk/dmraid_nvidia.c
@@ -107,7 +107,7 @@ grub_dmraid_nv_detect (grub_disk_t disk,
     /* Skip partition.  */
     return NULL;
 
-  sector = grub_disk_get_size (disk);
+  sector = grub_disk_native_sectors (disk);
   if (sector == GRUB_DISK_SIZE_UNKNOWN)
     /* Not raid.  */
     return NULL;
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index 9e20af70e..f077b5f55 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -867,7 +867,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       if (ctx.hd->partition_start == 0
 	  && (ctx.hd->partition_size << (parent->log_sector_size
 					 - GRUB_DISK_SECTOR_BITS))
-	  == grub_disk_get_size (parent))
+	  == grub_disk_native_sectors (parent))
 	{
 	  dev_name = grub_strdup (parent->name);
 	}
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 0175ce4c4..2f34a35e6 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -258,7 +258,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
     return NULL;
 
-  sector = grub_disk_get_size (disk);
+  sector = grub_disk_native_sectors (disk);
   if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
     return NULL;
 
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_sectors = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = grub_disk_native_sectors (disk) - 1;
   grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
   COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
   return newdev;
@@ -420,7 +420,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
   if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
     return grub_error (GRUB_ERR_BUG, "mdlen is too long");
 
-  sector = grub_disk_get_size (source);
+  sector = grub_disk_native_sectors (source);
   if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
     return grub_error (GRUB_ERR_BUG, "not a geli");
 
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 58f8a53e1..912e88255 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -821,7 +821,7 @@ grub_ldm_detect (grub_disk_t disk,
 	    /* LDM is never inside a partition.  */
 	    if (!has_ldm || disk->partition)
 	      continue;
-	    sector = grub_disk_get_size (disk);
+	    sector = grub_disk_native_sectors (disk);
 	    if (sector == GRUB_DISK_SIZE_UNKNOWN)
 	      continue;
 	    sector--;
@@ -938,7 +938,7 @@ grub_util_is_ldm (grub_disk_t disk)
 	  /* LDM is never inside a partition.  */
 	  if (!has_ldm || disk->partition)
 	    continue;
-	  sector = grub_disk_get_size (disk);
+	  sector = grub_disk_native_sectors (disk);
 	  if (sector == GRUB_DISK_SIZE_UNKNOWN)
 	    continue;
 	  sector--;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index aa9877b68..5fc79d880 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = 9;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
+  newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c
index c980feba4..38444b02c 100644
--- a/grub-core/disk/mdraid1x_linux.c
+++ b/grub-core/disk/mdraid1x_linux.c
@@ -111,7 +111,7 @@ grub_mdraid_detect (grub_disk_t disk,
   grub_uint64_t size;
   grub_uint8_t minor_version;
 
-  size = grub_disk_get_size (disk);
+  size = grub_disk_native_sectors (disk);
 
   /* Check for an 1.x superblock.
    * It's always aligned to a 4K boundary
diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c
index 11024ae31..e40216f51 100644
--- a/grub-core/disk/mdraid_linux.c
+++ b/grub-core/disk/mdraid_linux.c
@@ -190,7 +190,7 @@ grub_mdraid_detect (grub_disk_t disk,
   struct grub_diskfilter_vg *ret;
 
   /* The sector where the mdraid 0.90 superblock is stored, if available.  */
-  size = grub_disk_get_size (disk);
+  size = grub_disk_native_sectors (disk);
   if (size == GRUB_DISK_SIZE_UNKNOWN)
     /* not 0.9x raid.  */
     return NULL;
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 857bea991..581215ef1 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -148,16 +148,16 @@ grub_cbfs_mount (grub_disk_t disk)
   grub_off_t header_off;
   struct cbfs_header head;
 
-  if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
+  if (grub_disk_native_sectors (disk) == GRUB_DISK_SIZE_UNKNOWN)
     goto fail;
 
-  if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
+  if (grub_disk_read (disk, grub_disk_native_sectors (disk) - 1,
 		      GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
 		      sizeof (ptr), &ptr))
     goto fail;
 
   ptr = grub_cpu_to_le32 (ptr);
-  header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  header_off = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     + (grub_int32_t) ptr;
 
   if (grub_disk_read (disk, 0, header_off,
@@ -171,16 +171,16 @@ grub_cbfs_mount (grub_disk_t disk)
   if (!data)
     goto fail;
 
-  data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  data->cbfs_start = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset));
-  data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     - grub_be_to_cpu32 (head.bootblocksize);
   data->cbfs_align = grub_be_to_cpu32 (head.align);
 
-  if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
+  if (data->cbfs_start >= (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
     goto fail;
-  if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
-    data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS);
+  if (data->cbfs_end > (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
+    data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS);
 
   data->next_hofs = data->cbfs_start;
 
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 7ed148d3b..082326f38 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -753,7 +753,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
     partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size)
 		      >> GRUB_DISK_SECTOR_BITS);
   else
-    partition_size = grub_disk_get_size (disk);
+    partition_size = grub_disk_native_sectors (disk);
   if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
     {
       /* Read second super block. */
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index 41ef0ff57..b6e1e178d 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -1175,7 +1175,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
   desc.original = original;
 
   /* Don't check back labels on CDROM.  */
-  if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
+  if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
     vdevnum = VDEV_LABELS / 2;
 
   for (label = 0; ubbest == NULL && label < vdevnum; label++)
@@ -1184,7 +1184,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
 	= label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
 	+ ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
 	+ (label < VDEV_LABELS / 2 ? 0 : 
-	   ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t))
+	   ALIGN_DOWN (grub_disk_native_sectors (dev->disk), sizeof (vdev_label_t))
 	   - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
 
       /* Read in the uberblock ring (128K). */
diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
index ffb09c8ee..e1b0e073e 100644
--- a/grub-core/kern/disk.c
+++ b/grub-core/kern/disk.c
@@ -533,7 +533,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
 }
 
 grub_uint64_t
-grub_disk_get_size (grub_disk_t disk)
+grub_disk_native_sectors (grub_disk_t disk)
 {
   if (disk->partition)
     return grub_partition_get_len (disk->partition);
diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
index 3834a1490..2ed3ff319 100644
--- a/grub-core/kern/mips/arc/init.c
+++ b/grub-core/kern/mips/arc/init.c
@@ -430,7 +430,7 @@ grub_machine_get_bootlocation (char **device, char **path)
     }
 
   if (poff == 0
-      && pend == grub_disk_get_size (parent))
+      && pend == grub_disk_native_sectors (parent))
     {
       grub_disk_close (parent);
       *device = dname;
diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c
index 435cd9234..8bb6da31f 100644
--- a/grub-core/normal/misc.c
+++ b/grub-core/normal/misc.c
@@ -176,14 +176,14 @@ grub_normal_print_device_info (const char *name)
 		     (grub_partition_get_start (dev->disk->partition) & 1) ? ".5" : "" );
       else
 	grub_printf_ (N_(" - Sector size %uB"), 1 << dev->disk->log_sector_size);
-      if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
+      if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
 	grub_puts_ (N_(" - Total size unknown"));
       else
 	grub_printf (_(" - Total size %llu%sKiB"),
-		     (unsigned long long) (grub_disk_get_size (dev->disk) >> 1),
+		     (unsigned long long) (grub_disk_native_sectors (dev->disk) >> 1),
 		     /* TRANSLATORS: Replace dot with appropriate decimal separator for
 			your language.  */
-		     (grub_disk_get_size (dev->disk) & 1) ? _(".5") : "");
+		     (grub_disk_native_sectors (dev->disk) & 1) ? _(".5") : "");
     }
 
   if (dev)
diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
index 1ef86bf58..253f8d101 100644
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -371,7 +371,7 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
 
   hddp->partition_start = grub_partition_get_start (efidir_grub_dev->disk->partition)
     >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
-  hddp->partition_size = grub_disk_get_size (efidir_grub_dev->disk)
+  hddp->partition_size = grub_disk_native_sectors (efidir_grub_dev->disk)
     >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
 
   pathptr = hddp + 1;
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 132a1bb75..0fb727d3d 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -171,7 +171,7 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 
 #define GRUB_DISK_MAX_MAX_AGGLOMERATE ((1 << (30 - GRUB_DISK_CACHE_BITS - GRUB_DISK_SECTOR_BITS)) - 1)
 
-/* Return value of grub_disk_get_size() in case disk size is unknown. */
+/* Return value of grub_disk_native_sectors() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
 /* Convert to GRUB native disk sized sector from disk sized sector. */
@@ -219,7 +219,7 @@ extern grub_err_t (*EXPORT_VAR(grub_disk_write_weak)) (grub_disk_t disk,
 						       const void *buf);
 
 
-grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
+grub_uint64_t EXPORT_FUNC(grub_disk_native_sectors) (grub_disk_t disk);
 
 #if DISK_CACHE_STATS
 void
diff --git a/util/grub-install.c b/util/grub-install.c
index a35a2e2e8..f9f8ee7b2 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -748,7 +748,7 @@ is_prep_empty (grub_device_t dev)
   grub_disk_addr_t dsize, addr;
   grub_uint32_t buffer[32768];
 
-  dsize = grub_disk_get_size (dev->disk);
+  dsize = grub_disk_native_sectors (dev->disk);
   for (addr = 0; addr < dsize;
        addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
     {
diff --git a/util/grub-probe.c b/util/grub-probe.c
index cbe6ed94c..c08e46bbb 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -398,7 +398,7 @@ probe (const char *path, char **device_names, char delim)
 	  if (! dev || !dev->disk)
 	    grub_util_error ("%s", grub_errmsg);
 
-	  dsize = grub_disk_get_size (dev->disk);
+	  dsize = grub_disk_native_sectors (dev->disk);
 	  for (addr = 0; addr < dsize;
 	       addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
 	    {
-- 
2.27.0



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

* [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:24             ` Patrick Steinhardt
  2020-12-07 19:50             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 03/17] luks2: Remove unused argument in grub_error Glenn Washburn
                             ` (15 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This ensures that expected order of operations is preserved when arguments
are expressions.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 include/grub/misc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index b7ca6dd58..780a34e90 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -28,10 +28,10 @@
 #include <grub/compiler.h>
 
 #define ALIGN_UP(addr, align) \
-	((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
+	(((addr) + (typeof (addr)) (align) - 1) & ~((typeof (addr)) (align) - 1))
 #define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 1))
 #define ALIGN_DOWN(addr, align) \
-	((addr) & ~((typeof (addr)) align - 1))
+	((addr) & ~((typeof (addr)) (align) - 1))
 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
 #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
 
-- 
2.27.0



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

* [PATCH v7 03/17] luks2: Remove unused argument in grub_error
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
  2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
  2020-12-04 16:43           ` [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:25             ` Patrick Steinhardt
  2020-12-07 19:52             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
                             ` (14 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d96764a02..bdb90e4b6 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -200,7 +200,7 @@ luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
       grub_json_getstring (&out->size, segment, "size") ||
       grub_json_getstring (&out->encryption, segment, "encryption") ||
       grub_json_getint64 (&out->sector_size, segment, "sector_size"))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters", type);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters");
 
   return GRUB_ERR_NONE;
 }
@@ -228,7 +228,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no segments", type);
+		       "Digest references no segments");
 
   for (i = 0; i < size; i++)
     {
@@ -240,7 +240,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &keyslots))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no keyslots", type);
+		       "Digest references no keyslots");
 
   for (i = 0; i < size; i++)
     {
-- 
2.27.0



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

* [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (2 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 03/17] luks2: Remove unused argument in grub_error Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:26             ` Patrick Steinhardt
  2020-12-07 19:58             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
                             ` (13 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

We should assume that the output argument "out" is uninitialized and could
have random data. So, make sure to initialize the segments and keyslots bit
fields because potentially not all bits of those fields are written to.
Otherwise, the digest could say it belongs to keyslots and segments that it
does not.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index bdb90e4b6..eadd529e9 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -230,6 +230,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
 		       "Digest references no segments");
 
+  out->segments = 0;
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&o, &segments, i) ||
@@ -242,6 +243,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
 		       "Digest references no keyslots");
 
+  out->keyslots = 0;
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&o, &keyslots, i) ||
-- 
2.27.0



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

* [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (3 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:29             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
                             ` (12 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows code using these structs to know the named key associated with
these json data structures. In the future we can use these to provide better
error messages to the user.

Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
used for both keyslot and segment slot keys.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index eadd529e9..437c1da07 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,8 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  /* The integer key to the associative array of keyslots */
+  grub_uint64_t json_slot_key;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -103,6 +105,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
 
 struct grub_luks2_segment
 {
+  grub_uint64_t json_slot_key;
   grub_uint64_t offset;
   const char	*size;
   const char	*encryption;
@@ -112,6 +115,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
 
 struct grub_luks2_digest
 {
+  grub_uint64_t json_slot_key;
   /* Both keyslots and segments are interpreted as bitfields here */
   grub_uint64_t	keyslots;
   grub_uint64_t	segments;
@@ -261,12 +265,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t idx;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
@@ -278,11 +281,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << k->json_slot_key)))
 	break;
     }
   if (i == size)
@@ -295,12 +299,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&segment, &segments, i) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << s->json_slot_key)))
 	break;
     }
   if (i == size)
-- 
2.27.0



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

* [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (4 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:31             ` Patrick Steinhardt
  2020-12-07 20:15             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index Glenn Washburn
                             ` (11 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the slot key name in the json array rather than the 0 based index in the
json array for keyslots, segments, and digests. This is less confusing for
the end user. For example, say you have a LUKS2 device with a key in slot 1
and slot 4. When using the password for slot 4 to unlock the device, the
messages using the index of the keyslot will mention keyslot 1 (its a
zero-based index). Furthermore, with this change the keyslot number will
align with the number used to reference the keyslot when using the
--key-slot argument to cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 437c1da07..ea1065bcf 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -284,13 +284,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
           grub_json_getchild (&digest, &digest, 0) ||
           luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->json_slot_key)))
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
 
   return GRUB_ERR_NONE;
 }
@@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -623,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
+			keyslot.slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index.
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (5 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:31             ` Patrick Steinhardt
  2020-12-07 20:17             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
                             ` (10 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows error messages to be more easily distinguishable between indexes
and slot keys. The former include the string "index" in the error/debug
string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index ea1065bcf..4be40b22b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -272,7 +272,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -302,7 +302,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
           luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->json_slot_key)))
 	break;
-- 
2.27.0



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

* [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (6 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:32             ` Patrick Steinhardt
  2020-12-07 20:18             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
                             ` (9 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 7 ++++---
 include/grub/types.h        | 2 ++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 473c93976..0e955a020 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -281,20 +281,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
+	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
 	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
+					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
 				    & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
 	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
 	  }
 	  break;
diff --git a/include/grub/types.h b/include/grub/types.h
index f22055f98..9989e3a16 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -80,6 +80,8 @@
 # define GRUB_CHAR_BIT	__CHAR_BIT__
 #endif
 
+#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
+
 /* Define various wide integers.  */
 typedef signed char		grub_int8_t;
 typedef short			grub_int16_t;
-- 
2.27.0



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

* [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (7 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:33             ` Patrick Steinhardt
  2020-12-07 20:22             ` Daniel Kiper
  2020-12-04 16:43           ` [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
                             ` (8 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
unsigned number with size of type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 8 ++++----
 include/grub/types.h        | 7 +++++++
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 0e955a020..5aa0c4720 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
 					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
 	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 9989e3a16..0542011cc 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+/*
+  Cast to unsigned long long so that the "return value" is always a consistent
+  type and to ensure an unsigned value regardless of type parameter.
+ */
+#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
+#define GRUB_TYPE_U_MIN(type) 0ULL
+
 typedef grub_uint64_t grub_properly_aligned_t;
 
 #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
-- 
2.27.0



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

* [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (8 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:34             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                             ` (7 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

We need to convert the sectors from the size of the underlying device to the
cryptodisk sector size; segment.size is in bytes which need to be converted
to cryptodisk sectors as well.

Also, removed an empty statement.

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 4be40b22b..bdf40768b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
+			       - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (9 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 19:21             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
                             ` (6 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 5aa0c4720..b62835acc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t iv64;
+
+	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    grub_set_unaligned64 (iv, iv64);
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+	  /* The IV is the 64 bit byte offset of the sector. */
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
-					       - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+					       - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 5fc79d880..13103ea6a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
   newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  GRUB_LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index bdf40768b..de2e70796 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      GRUB_LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index c9bf7597a..938912cf3 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -144,7 +150,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (10 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 19:35             ` Patrick Steinhardt
  2020-12-08  4:28             ` Glenn Washburn
  2020-12-04 16:43           ` [PATCH v7 13/17] luks2: Error check segment.sector_size Glenn Washburn
                             ` (5 subsequent siblings)
  17 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

First, check to make sure that source disk has a known size. If not, print
debug message and return error. There are 4 cases where
GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
all those cases processing continues. So this is probably a bit
conservative. However, 3 of the cases seem pathological, and the other,
biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
volume on a cd is a big use case, we'll error until someone complains.

Do some sanity checking on data coming from the luks header. If segment.size
is "dynamic",

Check for errors from grub_strtoull when converting segment size from
string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
returned, then there was an overflow in converting to a 64-bit unsigned
integer. So this could be a very large disk (perhaps large raid array).
In this case, we want to continue to try to use this key so long as the
source disk's size is greater than this segment size. Otherwise, this is
an invalid segment, and continue on to the next key.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 98 +++++++++++++++++++++++++++++++++++++-----
 include/grub/disk.h    | 17 ++++++++
 2 files changed, 105 insertions(+), 10 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index de2e70796..1bb3a333d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key);
 
   return GRUB_ERR_NONE;
 }
@@ -600,37 +600,115 @@ luks2_recover_key (grub_disk_t source,
       goto err;
     }
 
+  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+    {
+      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
+      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
+			     "conservatively returning error\n", source->name);
+      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
+      goto err;
+    }
+
   /* Try all keyslot */
   for (i = 0; i < size; i++)
     {
+      typeof(source->total_sectors) max_crypt_sectors = 0;
+
+      grub_errno = GRUB_ERR_NONE;
       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
       if (ret)
 	goto err;
+      if (grub_errno != GRUB_ERR_NONE)
+	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
+	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
 	  continue;
         }
 
-      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
+      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      /* Set to the source disk size, which is the maximum we allow. */
+      max_crypt_sectors = grub_disk_convert_sector(source,
+						   source->total_sectors,
+						   crypt->log_sector_size);
+
+      if (max_crypt_sectors < crypt->offset_sectors)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
+				 " %"PRIuGRUB_UINT64_T" which is greater than"
+				 " source disk size %"PRIuGRUB_UINT64_T","
+				 " skipping\n",
+				 segment.json_slot_key, crypt->offset_sectors,
+				 max_crypt_sectors);
+	  continue;
+	}
+
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
-			       - crypt->offset_sectors;
+	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	{
+	  grub_errno = GRUB_ERR_NONE;
+	  /* Convert segment.size to sectors, rounding up to nearest sector */
+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
+					   1 << crypt->log_sector_size);
+	  crypt->total_sectors >>= crypt->log_sector_size;
+
+	  if (grub_errno == GRUB_ERR_NONE)
+	    ;
+	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
+	    {
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " \"%s\" is not a parsable number\n",
+				     segment.json_slot_key, segment.size);
+	      continue;
+	    }
+	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+	    {
+	      /*
+	       * There was an overflow in parsing segment.size, so disk must
+	       * be very large or the string is incorrect.
+	       */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " %s overflowed 64-bit unsigned integer,"
+				     " the end of the crypto device will be"
+				     " inaccessible\n",
+				     segment.json_slot_key, segment.size);
+	      if (crypt->total_sectors > max_crypt_sectors)
+		crypt->total_sectors = max_crypt_sectors;
+	    }
+	}
+
+      if (crypt->total_sectors == 0)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
+				 " sectors, skipping\n",
+				 segment.json_slot_key);
+	  continue;
+	}
+      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
+				 " data position greater than source disk size,"
+				 " the end of the crypto device will be"
+				 " inaccessible\n",
+				 segment.json_slot_key);
+	  /* Allow decryption up to the end of the source disk. */
+	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
+	}
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
 	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
-			keyslot.slot_key, grub_errmsg);
+			keyslot.json_slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -638,7 +716,7 @@ luks2_recover_key (grub_disk_t source,
       if (ret)
 	{
 	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
-			keyslot.slot_key, grub_errmsg);
+			keyslot.json_slot_key, grub_errmsg);
 	  continue;
 	}
 
@@ -646,7 +724,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
+      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.json_slot_key);
 
       candidate_key_len = keyslot.key_size;
       break;
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 0fb727d3d..f9227f285 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -27,6 +27,8 @@
 #include <grub/device.h>
 /* For NULL.  */
 #include <grub/mm.h>
+/* For ALIGN_UP.  */
+#include <grub/misc.h>
 
 /* These are used to set a device id. When you add a new disk device,
    you must define a new id for it here.  */
@@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
+/* Convert sector number from disk sized sectors to a log-size sized sector. */
+static inline grub_disk_addr_t
+grub_disk_convert_sector (grub_disk_t disk,
+			  grub_disk_addr_t sector,
+			  grub_size_t log_sector_size)
+{
+  if (disk->log_sector_size < log_sector_size)
+    {
+      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));
+      return sector >> (log_sector_size - disk->log_sector_size);
+    }
+  else
+    return sector << (disk->log_sector_size - log_sector_size);
+}
+
 /* Convert to GRUB native disk sized sector from disk sized sector. */
 static inline grub_disk_addr_t
 grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
-- 
2.27.0



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

* [PATCH v7 13/17] luks2: Error check segment.sector_size
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (11 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 19:35             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 14/17] whitespace: convert 8 spaces to tabs Glenn Washburn
                             ` (4 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 1bb3a333d..499c9330b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -629,6 +629,17 @@ luks2_recover_key (grub_disk_t source,
 
       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
 
+      /* Sector size should be one of 512, 1024, 2048, or 4096. */
+      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
+	    segment.sector_size == 2048 || segment.sector_size == 4096))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
+				 " size %"PRIuGRUB_UINT64_T" is not one of"
+				 " 512, 1024, 2048, or 4096\n",
+				 segment.json_slot_key, segment.sector_size);
+	  continue;
+	}
+
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
-- 
2.27.0



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

* [PATCH v7 14/17] whitespace: convert 8 spaces to tabs
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (12 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 13/17] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:35             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 15/17] mips: Enable __clzdi2() Glenn Washburn
                             ` (3 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 499c9330b..2335ded77 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -282,8 +282,8 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
     {
       if (grub_json_getchild (&digest, &digests, i) ||
 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
-          grub_json_getchild (&digest, &digest, 0) ||
-          luks2_parse_digest (d, &digest))
+	  grub_json_getchild (&digest, &digest, 0) ||
+	  luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << k->json_slot_key)))
@@ -301,7 +301,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       if (grub_json_getchild (&segment, &segments, i) ||
 	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
-          luks2_parse_segment (s, &segment))
+	  luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << s->json_slot_key)))
@@ -625,7 +625,7 @@ luks2_recover_key (grub_disk_t source,
 	{
 	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
 	  continue;
-        }
+	}
 
       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
 
-- 
2.27.0



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

* [PATCH v7 15/17] mips: Enable __clzdi2()
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (13 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 14/17] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 19:36             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
                             ` (2 subsequent siblings)
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
__clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
enabled.

Suggested-by: Daniel Kiper <dkiper@net-space.pl>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/kern/compiler-rt.c | 2 +-
 include/grub/compiler-rt.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index a464200c6..2057c2e0c 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
 }
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 __clzdi2 (grub_uint64_t val)
 {
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
index 7591980b4..17828b322 100644
--- a/include/grub/compiler-rt.h
+++ b/include/grub/compiler-rt.h
@@ -115,7 +115,7 @@ int
 EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
 #endif
-- 
2.27.0



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

* [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (14 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 15/17] mips: Enable __clzdi2() Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 13:36             ` Patrick Steinhardt
  2020-12-04 16:43           ` [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  2020-12-06 13:38           ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 include/grub/misc.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index 780a34e90..73a514eb1 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 
+#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
+                         - __builtin_clzll (n) - 1)
+
 #endif /* ! GRUB_MISC_HEADER */
-- 
2.27.0



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

* [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (15 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-12-04 16:43           ` Glenn Washburn
  2020-12-06 19:44             ` Patrick Steinhardt
  2020-12-06 13:38           ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
  17 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-04 16:43 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2335ded77..4fa5a0dbc 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -642,8 +642,7 @@ luks2_recover_key (grub_disk_t source,
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
-      crypt->log_sector_size = sizeof (unsigned int) * 8
-		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      crypt->log_sector_size = grub_log2ull (segment.sector_size);
       /* Set to the source disk size, which is the maximum we allow. */
       max_crypt_sectors = grub_disk_convert_sector(source,
 						   source->total_sectors,
-- 
2.27.0



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

* Re: [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors
  2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
@ 2020-12-06 13:24             ` Patrick Steinhardt
  2020-12-07 19:38             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:24 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:30AM -0600, Glenn Washburn wrote:
> The function grub_disk_get_size is confusingly named because it actually
> returns a sector count where the sectors are sized in the grub native sector
> size. Rename to something more appropriate.
> 
> Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/diskfilter.c        | 12 ++++++------
>  grub-core/disk/dmraid_nvidia.c     |  2 +-
>  grub-core/disk/efi/efidisk.c       |  2 +-
>  grub-core/disk/geli.c              |  6 +++---
>  grub-core/disk/ldm.c               |  4 ++--
>  grub-core/disk/luks.c              |  2 +-
>  grub-core/disk/mdraid1x_linux.c    |  2 +-
>  grub-core/disk/mdraid_linux.c      |  2 +-
>  grub-core/fs/cbfs.c                | 16 ++++++++--------
>  grub-core/fs/nilfs2.c              |  2 +-
>  grub-core/fs/zfs/zfs.c             |  4 ++--
>  grub-core/kern/disk.c              |  2 +-
>  grub-core/kern/mips/arc/init.c     |  2 +-
>  grub-core/normal/misc.c            |  6 +++---
>  grub-core/osdep/windows/platform.c |  2 +-
>  include/grub/disk.h                |  4 ++--
>  util/grub-install.c                |  2 +-
>  util/grub-probe.c                  |  2 +-
>  18 files changed, 37 insertions(+), 37 deletions(-)
> 
> diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
> index 86557f923..032011566 100644
> --- a/grub-core/disk/diskfilter.c
> +++ b/grub-core/disk/diskfilter.c
> @@ -148,7 +148,7 @@ scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
>  	if (m->disk && m->disk->id == disk->id
>  	    && m->disk->dev->id == disk->dev->id
>  	    && m->part_start == grub_partition_get_start (disk->partition)
> -	    && m->part_size == grub_disk_get_size (disk))
> +	    && m->part_size == grub_disk_native_sectors (disk))
>  	  return 0;
>      }
>  
> @@ -1190,13 +1190,13 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
>  
>    grub_dprintf ("diskfilter", "Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name,
>  		(unsigned long long) grub_partition_get_start (disk->partition),
> -		(unsigned long long) grub_disk_get_size (disk),
> +		(unsigned long long) grub_disk_native_sectors (disk),
>  		array->name, diskfilter->name);
>  #ifdef GRUB_UTIL
>    grub_util_info ("Inserting %s (+%" GRUB_HOST_PRIuLONG_LONG ",%"
>  		  GRUB_HOST_PRIuLONG_LONG ") into %s (%s)\n", disk->name,
>  		  (unsigned long long) grub_partition_get_start (disk->partition),
> -		  (unsigned long long) grub_disk_get_size (disk),
> +		  (unsigned long long) grub_disk_native_sectors (disk),
>  		  array->name, diskfilter->name);
>    array->driver = diskfilter;
>  #endif
> @@ -1210,7 +1210,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
>  	struct grub_diskfilter_lv *lv;
>  	/* FIXME: Check whether the update time of the superblocks are
>  	   the same.  */
> -	if (pv->disk && grub_disk_get_size (disk) >= pv->part_size)
> +	if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size)
>  	  return GRUB_ERR_NONE;
>  	pv->disk = grub_disk_open (disk->name);
>  	if (!pv->disk)
> @@ -1219,7 +1219,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
>  	   raid device, we shouldn't change it.  */
>  	pv->start_sector -= pv->part_start;
>  	pv->part_start = grub_partition_get_start (disk->partition);
> -	pv->part_size = grub_disk_get_size (disk);
> +	pv->part_size = grub_disk_native_sectors (disk);
>  
>  #ifdef GRUB_UTIL
>  	{
> @@ -1311,7 +1311,7 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
>  	if (pv->disk && pv->disk->id == disk->id
>  	    && pv->disk->dev->id == disk->dev->id
>  	    && pv->part_start == grub_partition_get_start (disk->partition)
> -	    && pv->part_size == grub_disk_get_size (disk))
> +	    && pv->part_size == grub_disk_native_sectors (disk))
>  	  {
>  	    if (vg_out)
>  	      *vg_out = vg;
> diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c
> index 060279124..4d2fb04d1 100644
> --- a/grub-core/disk/dmraid_nvidia.c
> +++ b/grub-core/disk/dmraid_nvidia.c
> @@ -107,7 +107,7 @@ grub_dmraid_nv_detect (grub_disk_t disk,
>      /* Skip partition.  */
>      return NULL;
>  
> -  sector = grub_disk_get_size (disk);
> +  sector = grub_disk_native_sectors (disk);
>    if (sector == GRUB_DISK_SIZE_UNKNOWN)
>      /* Not raid.  */
>      return NULL;
> diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
> index 9e20af70e..f077b5f55 100644
> --- a/grub-core/disk/efi/efidisk.c
> +++ b/grub-core/disk/efi/efidisk.c
> @@ -867,7 +867,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
>        if (ctx.hd->partition_start == 0
>  	  && (ctx.hd->partition_size << (parent->log_sector_size
>  					 - GRUB_DISK_SECTOR_BITS))
> -	  == grub_disk_get_size (parent))
> +	  == grub_disk_native_sectors (parent))
>  	{
>  	  dev_name = grub_strdup (parent->name);
>  	}
> diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
> index 0175ce4c4..2f34a35e6 100644
> --- a/grub-core/disk/geli.c
> +++ b/grub-core/disk/geli.c
> @@ -258,7 +258,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
>      return NULL;
>  
> -  sector = grub_disk_get_size (disk);
> +  sector = grub_disk_native_sectors (disk);
>    if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
>      return NULL;
>  
> @@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>  
>    newdev->modname = "geli";
>  
> -  newdev->total_sectors = grub_disk_get_size (disk) - 1;
> +  newdev->total_sectors = grub_disk_native_sectors (disk) - 1;
>    grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
>    COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
>    return newdev;
> @@ -420,7 +420,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
>    if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
>      return grub_error (GRUB_ERR_BUG, "mdlen is too long");
>  
> -  sector = grub_disk_get_size (source);
> +  sector = grub_disk_native_sectors (source);
>    if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
>      return grub_error (GRUB_ERR_BUG, "not a geli");
>  
> diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
> index 58f8a53e1..912e88255 100644
> --- a/grub-core/disk/ldm.c
> +++ b/grub-core/disk/ldm.c
> @@ -821,7 +821,7 @@ grub_ldm_detect (grub_disk_t disk,
>  	    /* LDM is never inside a partition.  */
>  	    if (!has_ldm || disk->partition)
>  	      continue;
> -	    sector = grub_disk_get_size (disk);
> +	    sector = grub_disk_native_sectors (disk);
>  	    if (sector == GRUB_DISK_SIZE_UNKNOWN)
>  	      continue;
>  	    sector--;
> @@ -938,7 +938,7 @@ grub_util_is_ldm (grub_disk_t disk)
>  	  /* LDM is never inside a partition.  */
>  	  if (!has_ldm || disk->partition)
>  	    continue;
> -	  sector = grub_disk_get_size (disk);
> +	  sector = grub_disk_native_sectors (disk);
>  	  if (sector == GRUB_DISK_SIZE_UNKNOWN)
>  	    continue;
>  	  sector--;
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index aa9877b68..5fc79d880 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
>    newdev->log_sector_size = 9;
> -  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
> +  newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
>  
> diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c
> index c980feba4..38444b02c 100644
> --- a/grub-core/disk/mdraid1x_linux.c
> +++ b/grub-core/disk/mdraid1x_linux.c
> @@ -111,7 +111,7 @@ grub_mdraid_detect (grub_disk_t disk,
>    grub_uint64_t size;
>    grub_uint8_t minor_version;
>  
> -  size = grub_disk_get_size (disk);
> +  size = grub_disk_native_sectors (disk);
>  
>    /* Check for an 1.x superblock.
>     * It's always aligned to a 4K boundary
> diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c
> index 11024ae31..e40216f51 100644
> --- a/grub-core/disk/mdraid_linux.c
> +++ b/grub-core/disk/mdraid_linux.c
> @@ -190,7 +190,7 @@ grub_mdraid_detect (grub_disk_t disk,
>    struct grub_diskfilter_vg *ret;
>  
>    /* The sector where the mdraid 0.90 superblock is stored, if available.  */
> -  size = grub_disk_get_size (disk);
> +  size = grub_disk_native_sectors (disk);
>    if (size == GRUB_DISK_SIZE_UNKNOWN)
>      /* not 0.9x raid.  */
>      return NULL;
> diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
> index 857bea991..581215ef1 100644
> --- a/grub-core/fs/cbfs.c
> +++ b/grub-core/fs/cbfs.c
> @@ -148,16 +148,16 @@ grub_cbfs_mount (grub_disk_t disk)
>    grub_off_t header_off;
>    struct cbfs_header head;
>  
> -  if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
> +  if (grub_disk_native_sectors (disk) == GRUB_DISK_SIZE_UNKNOWN)
>      goto fail;
>  
> -  if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
> +  if (grub_disk_read (disk, grub_disk_native_sectors (disk) - 1,
>  		      GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
>  		      sizeof (ptr), &ptr))
>      goto fail;
>  
>    ptr = grub_cpu_to_le32 (ptr);
> -  header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
> +  header_off = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
>      + (grub_int32_t) ptr;
>  
>    if (grub_disk_read (disk, 0, header_off,
> @@ -171,16 +171,16 @@ grub_cbfs_mount (grub_disk_t disk)
>    if (!data)
>      goto fail;
>  
> -  data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
> +  data->cbfs_start = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
>      - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset));
> -  data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
> +  data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
>      - grub_be_to_cpu32 (head.bootblocksize);
>    data->cbfs_align = grub_be_to_cpu32 (head.align);
>  
> -  if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
> +  if (data->cbfs_start >= (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
>      goto fail;
> -  if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
> -    data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS);
> +  if (data->cbfs_end > (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
> +    data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS);
>  
>    data->next_hofs = data->cbfs_start;
>  
> diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
> index 7ed148d3b..082326f38 100644
> --- a/grub-core/fs/nilfs2.c
> +++ b/grub-core/fs/nilfs2.c
> @@ -753,7 +753,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
>      partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size)
>  		      >> GRUB_DISK_SECTOR_BITS);
>    else
> -    partition_size = grub_disk_get_size (disk);
> +    partition_size = grub_disk_native_sectors (disk);
>    if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
>      {
>        /* Read second super block. */
> diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
> index 41ef0ff57..b6e1e178d 100644
> --- a/grub-core/fs/zfs/zfs.c
> +++ b/grub-core/fs/zfs/zfs.c
> @@ -1175,7 +1175,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
>    desc.original = original;
>  
>    /* Don't check back labels on CDROM.  */
> -  if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
> +  if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
>      vdevnum = VDEV_LABELS / 2;
>  
>    for (label = 0; ubbest == NULL && label < vdevnum; label++)
> @@ -1184,7 +1184,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
>  	= label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
>  	+ ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
>  	+ (label < VDEV_LABELS / 2 ? 0 : 
> -	   ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t))
> +	   ALIGN_DOWN (grub_disk_native_sectors (dev->disk), sizeof (vdev_label_t))
>  	   - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
>  
>        /* Read in the uberblock ring (128K). */
> diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
> index ffb09c8ee..e1b0e073e 100644
> --- a/grub-core/kern/disk.c
> +++ b/grub-core/kern/disk.c
> @@ -533,7 +533,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
>  }
>  
>  grub_uint64_t
> -grub_disk_get_size (grub_disk_t disk)
> +grub_disk_native_sectors (grub_disk_t disk)
>  {
>    if (disk->partition)
>      return grub_partition_get_len (disk->partition);
> diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
> index 3834a1490..2ed3ff319 100644
> --- a/grub-core/kern/mips/arc/init.c
> +++ b/grub-core/kern/mips/arc/init.c
> @@ -430,7 +430,7 @@ grub_machine_get_bootlocation (char **device, char **path)
>      }
>  
>    if (poff == 0
> -      && pend == grub_disk_get_size (parent))
> +      && pend == grub_disk_native_sectors (parent))
>      {
>        grub_disk_close (parent);
>        *device = dname;
> diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c
> index 435cd9234..8bb6da31f 100644
> --- a/grub-core/normal/misc.c
> +++ b/grub-core/normal/misc.c
> @@ -176,14 +176,14 @@ grub_normal_print_device_info (const char *name)
>  		     (grub_partition_get_start (dev->disk->partition) & 1) ? ".5" : "" );
>        else
>  	grub_printf_ (N_(" - Sector size %uB"), 1 << dev->disk->log_sector_size);
> -      if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
> +      if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
>  	grub_puts_ (N_(" - Total size unknown"));
>        else
>  	grub_printf (_(" - Total size %llu%sKiB"),
> -		     (unsigned long long) (grub_disk_get_size (dev->disk) >> 1),
> +		     (unsigned long long) (grub_disk_native_sectors (dev->disk) >> 1),
>  		     /* TRANSLATORS: Replace dot with appropriate decimal separator for
>  			your language.  */
> -		     (grub_disk_get_size (dev->disk) & 1) ? _(".5") : "");
> +		     (grub_disk_native_sectors (dev->disk) & 1) ? _(".5") : "");
>      }
>  
>    if (dev)
> diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
> index 1ef86bf58..253f8d101 100644
> --- a/grub-core/osdep/windows/platform.c
> +++ b/grub-core/osdep/windows/platform.c
> @@ -371,7 +371,7 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
>  
>    hddp->partition_start = grub_partition_get_start (efidir_grub_dev->disk->partition)
>      >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
> -  hddp->partition_size = grub_disk_get_size (efidir_grub_dev->disk)
> +  hddp->partition_size = grub_disk_native_sectors (efidir_grub_dev->disk)
>      >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
>  
>    pathptr = hddp + 1;
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index 132a1bb75..0fb727d3d 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -171,7 +171,7 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
>  
>  #define GRUB_DISK_MAX_MAX_AGGLOMERATE ((1 << (30 - GRUB_DISK_CACHE_BITS - GRUB_DISK_SECTOR_BITS)) - 1)
>  
> -/* Return value of grub_disk_get_size() in case disk size is unknown. */
> +/* Return value of grub_disk_native_sectors() in case disk size is unknown. */
>  #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
>  
>  /* Convert to GRUB native disk sized sector from disk sized sector. */
> @@ -219,7 +219,7 @@ extern grub_err_t (*EXPORT_VAR(grub_disk_write_weak)) (grub_disk_t disk,
>  						       const void *buf);
>  
>  
> -grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
> +grub_uint64_t EXPORT_FUNC(grub_disk_native_sectors) (grub_disk_t disk);
>  
>  #if DISK_CACHE_STATS
>  void
> diff --git a/util/grub-install.c b/util/grub-install.c
> index a35a2e2e8..f9f8ee7b2 100644
> --- a/util/grub-install.c
> +++ b/util/grub-install.c
> @@ -748,7 +748,7 @@ is_prep_empty (grub_device_t dev)
>    grub_disk_addr_t dsize, addr;
>    grub_uint32_t buffer[32768];
>  
> -  dsize = grub_disk_get_size (dev->disk);
> +  dsize = grub_disk_native_sectors (dev->disk);
>    for (addr = 0; addr < dsize;
>         addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
>      {
> diff --git a/util/grub-probe.c b/util/grub-probe.c
> index cbe6ed94c..c08e46bbb 100644
> --- a/util/grub-probe.c
> +++ b/util/grub-probe.c
> @@ -398,7 +398,7 @@ probe (const char *path, char **device_names, char delim)
>  	  if (! dev || !dev->disk)
>  	    grub_util_error ("%s", grub_errmsg);
>  
> -	  dsize = grub_disk_get_size (dev->disk);
> +	  dsize = grub_disk_native_sectors (dev->disk);
>  	  for (addr = 0; addr < dsize;
>  	       addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
>  	    {
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  2020-12-04 16:43           ` [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
@ 2020-12-06 13:24             ` Patrick Steinhardt
  2020-12-07 19:50             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:24 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:31AM -0600, Glenn Washburn wrote:
> This ensures that expected order of operations is preserved when arguments
> are expressions.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  include/grub/misc.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index b7ca6dd58..780a34e90 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -28,10 +28,10 @@
>  #include <grub/compiler.h>
>  
>  #define ALIGN_UP(addr, align) \
> -	((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
> +	(((addr) + (typeof (addr)) (align) - 1) & ~((typeof (addr)) (align) - 1))
>  #define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 1))
>  #define ALIGN_DOWN(addr, align) \
> -	((addr) & ~((typeof (addr)) align - 1))
> +	((addr) & ~((typeof (addr)) (align) - 1))
>  #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
>  #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
>  
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 03/17] luks2: Remove unused argument in grub_error
  2020-12-04 16:43           ` [PATCH v7 03/17] luks2: Remove unused argument in grub_error Glenn Washburn
@ 2020-12-06 13:25             ` Patrick Steinhardt
  2020-12-07 19:52             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:25 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:32AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index d96764a02..bdb90e4b6 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -200,7 +200,7 @@ luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
>        grub_json_getstring (&out->size, segment, "size") ||
>        grub_json_getstring (&out->encryption, segment, "encryption") ||
>        grub_json_getint64 (&out->sector_size, segment, "sector_size"))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters", type);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters");
>  
>    return GRUB_ERR_NONE;
>  }
> @@ -228,7 +228,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>  
>    if (grub_json_getsize (&size, &segments))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT,
> -		       "Digest references no segments", type);
> +		       "Digest references no segments");
>  
>    for (i = 0; i < size; i++)
>      {
> @@ -240,7 +240,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>  
>    if (grub_json_getsize (&size, &keyslots))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT,
> -		       "Digest references no keyslots", type);
> +		       "Digest references no keyslots");
>  
>    for (i = 0; i < size; i++)
>      {
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
  2020-12-04 16:43           ` [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
@ 2020-12-06 13:26             ` Patrick Steinhardt
  2020-12-07 19:58             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:26 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:33AM -0600, Glenn Washburn wrote:
> We should assume that the output argument "out" is uninitialized and could
> have random data. So, make sure to initialize the segments and keyslots bit
> fields because potentially not all bits of those fields are written to.
> Otherwise, the digest could say it belongs to keyslots and segments that it
> does not.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Makes sense.

Signed-off-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index bdb90e4b6..eadd529e9 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -230,6 +230,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>      return grub_error (GRUB_ERR_BAD_ARGUMENT,
>  		       "Digest references no segments");
>  
> +  out->segments = 0;
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&o, &segments, i) ||
> @@ -242,6 +243,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>      return grub_error (GRUB_ERR_BAD_ARGUMENT,
>  		       "Digest references no keyslots");
>  
> +  out->keyslots = 0;
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&o, &keyslots, i) ||
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-04 16:43           ` [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-12-06 13:29             ` Patrick Steinhardt
  2020-12-07 20:02               ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:29 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:34AM -0600, Glenn Washburn wrote:
> This allows code using these structs to know the named key associated with
> these json data structures. In the future we can use these to provide better
> error messages to the user.
> 
> Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
> used for both keyslot and segment slot keys.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Personally, I'd have named them `json_slot_idx`. But you've already done
so much work on improving the code that I don't want this to be the
reason to not give an SOB, especially considering that it's a strict
improvement anyway. So:

Signed-off-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index eadd529e9..437c1da07 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -65,6 +65,8 @@ typedef struct grub_luks2_header grub_luks2_header_t;
>  
>  struct grub_luks2_keyslot
>  {
> +  /* The integer key to the associative array of keyslots */
> +  grub_uint64_t json_slot_key;
>    grub_int64_t key_size;
>    grub_int64_t priority;
>    struct
> @@ -103,6 +105,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
>  
>  struct grub_luks2_segment
>  {
> +  grub_uint64_t json_slot_key;
>    grub_uint64_t offset;
>    const char	*size;
>    const char	*encryption;
> @@ -112,6 +115,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
>  
>  struct grub_luks2_digest
>  {
> +  grub_uint64_t json_slot_key;
>    /* Both keyslots and segments are interpreted as bitfields here */
>    grub_uint64_t	keyslots;
>    grub_uint64_t	segments;
> @@ -261,12 +265,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t idx;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> +      grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -278,11 +281,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&digest, &digests, i) ||
> +	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << idx)))
> +      if ((d->keyslots & (1 << k->json_slot_key)))
>  	break;
>      }
>    if (i == size)
> @@ -295,12 +299,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&segment, &segments, i) ||
> -	  grub_json_getuint64 (&idx, &segment, NULL) ||
> +	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->segments & (1 << idx)))
> +      if ((d->segments & (1 << s->json_slot_key)))
>  	break;
>      }
>    if (i == size)
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages
  2020-12-04 16:43           ` [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
@ 2020-12-06 13:31             ` Patrick Steinhardt
  2020-12-07 20:15             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:31 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:35AM -0600, Glenn Washburn wrote:
> Use the slot key name in the json array rather than the 0 based index in the
> json array for keyslots, segments, and digests. This is less confusing for
> the end user. For example, say you have a LUKS2 device with a key in slot 1
> and slot 4. When using the password for slot 4 to unlock the device, the
> messages using the index of the keyslot will mention keyslot 1 (its a
> zero-based index). Furthermore, with this change the keyslot number will
> align with the number used to reference the keyslot when using the
> --key-slot argument to cryptsetup.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

Oops. I just realized I gave SOBs on the previous patches. Naturally,
these should've been Reviewed-by's :(

> ---
>  grub-core/disk/luks2.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 437c1da07..ea1065bcf 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -284,13 +284,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->keyslots & (1 << k->json_slot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
>  
>    return GRUB_ERR_NONE;
>  }
> @@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
>  	  continue;
>          }
>  
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -623,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index.
  2020-12-04 16:43           ` [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index Glenn Washburn
@ 2020-12-06 13:31             ` Patrick Steinhardt
  2020-12-07 20:17             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:31 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:36AM -0600, Glenn Washburn wrote:
> This allows error messages to be more easily distinguishable between indexes
> and slot keys. The former include the string "index" in the error/debug
> string, and the later are surrounded in quotes.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index ea1065bcf..4be40b22b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -272,7 +272,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>        grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
>  
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
> @@ -302,7 +302,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>            luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->segments & (1 << s->json_slot_key)))
>  	break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-04 16:43           ` [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
@ 2020-12-06 13:32             ` Patrick Steinhardt
  2020-12-07 20:18             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:32 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:37AM -0600, Glenn Washburn wrote:
> The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
> type.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 7 ++++---
>  include/grub/types.h        | 2 ++
>  2 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 473c93976..0e955a020 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -281,20 +281,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> +	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
>  	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> +					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
>  				    & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
>  	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
>  	  }
>  	  break;
> diff --git a/include/grub/types.h b/include/grub/types.h
> index f22055f98..9989e3a16 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -80,6 +80,8 @@
>  # define GRUB_CHAR_BIT	__CHAR_BIT__
>  #endif
>  
> +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> +
>  /* Define various wide integers.  */
>  typedef signed char		grub_int8_t;
>  typedef short			grub_int16_t;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-04 16:43           ` [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
@ 2020-12-06 13:33             ` Patrick Steinhardt
  2020-12-07 20:22             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:33 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:38AM -0600, Glenn Washburn wrote:
> Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> unsigned number with size of type.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/cryptodisk.c | 8 ++++----
>  include/grub/types.h        | 7 +++++++
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 0e955a020..5aa0c4720 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
>  					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
>  	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 9989e3a16..0542011cc 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
>  #endif
>  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
>  
> +/*
> +  Cast to unsigned long long so that the "return value" is always a consistent
> +  type and to ensure an unsigned value regardless of type parameter.
> + */
> +#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
> +#define GRUB_TYPE_U_MIN(type) 0ULL
> +

Nit: multi-line comments do use the following format:

/*
 * Foo bar
 * bar foo
 /

Other than that:

Reviewed-by: Patrick Steinhardt <ps@pks.im>

>  typedef grub_uint64_t grub_properly_aligned_t;
>  
>  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-04 16:43           ` [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-12-06 13:34             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:34 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:39AM -0600, Glenn Washburn wrote:
> We need to convert the sectors from the size of the underlying device to the
> cryptodisk sector size; segment.size is in bytes which need to be converted
> to cryptodisk sectors as well.
> 
> Also, removed an empty statement.
> 
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 4be40b22b..bdf40768b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>    grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
>    grub_uint8_t *split_key = NULL;
>    grub_size_t saltlen = sizeof (salt);
> -  char cipher[32], *p;;
> +  char cipher[32], *p;
>    const gcry_md_spec_t *hash;
>    gcry_err_code_t gcry_ret;
>    grub_err_t ret;
> @@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
> +	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> +			       - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 14/17] whitespace: convert 8 spaces to tabs
  2020-12-04 16:43           ` [PATCH v7 14/17] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-12-06 13:35             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:35 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:43AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 499c9330b..2335ded77 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -282,8 +282,8 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>      {
>        if (grub_json_getchild (&digest, &digests, i) ||
>  	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
> -          grub_json_getchild (&digest, &digest, 0) ||
> -          luks2_parse_digest (d, &digest))
> +	  grub_json_getchild (&digest, &digest, 0) ||
> +	  luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->keyslots & (1 << k->json_slot_key)))
> @@ -301,7 +301,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>        if (grub_json_getchild (&segment, &segments, i) ||
>  	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
> -          luks2_parse_segment (s, &segment))
> +	  luks2_parse_segment (s, &segment))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>  
>        if ((d->segments & (1 << s->json_slot_key)))
> @@ -625,7 +625,7 @@ luks2_recover_key (grub_disk_t source,
>  	{
>  	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
>  	  continue;
> -        }
> +	}
>  
>        grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>  
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-12-04 16:43           ` [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-12-06 13:36             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:36 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:45AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  include/grub/misc.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index 780a34e90..73a514eb1 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
>  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
>  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
>  
> +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> +                         - __builtin_clzll (n) - 1)
> +
>  #endif /* ! GRUB_MISC_HEADER */
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
                             ` (16 preceding siblings ...)
  2020-12-04 16:43           ` [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
@ 2020-12-06 13:38           ` Patrick Steinhardt
  17 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 13:38 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:29AM -0600, Glenn Washburn wrote:
> This patch series is an update to reflect changes suggested in v6. Of note,
> there are a few new patches: 01, 02, and 04.
> 
>   01: Daniel suggested to renae grub_disk_get_size to grub_disk_native_sectors
>   02: Make ALIGN_UP and ALIGN_DOWN safer
>   04: Make luks2_parse_digest() safer

The patches I reviewed look good to me. I gotta jump, so I'll hopefully
get to the remaining patches this evening.

Also note that I accidentally posted SOBs for the first few ones. These
should've been Reviewed-by's.

Thanks for all your work!

Patrick

> Glenn
> 
> Glenn Washburn (17):
>   disk: Rename grub_disk_get_size to grub_disk_native_sectors
>   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
>   luks2: Remove unused argument in grub_error
>   luks2: Make sure all fields of output argument in luks2_parse_digest()
>     are written to
>   luks2: Add json_slot_key member to struct
>     grub_luks2_keyslot/segment/digest
>   luks2: Use more intuitive slot key instead of index in user messages
>   luks2: Add string "index" to user strings using a json index.
>   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
>   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
>   luks2: grub_cryptodisk_t->total_sectors is the max number of device
>     native sectors
>   cryptodisk: Properly handle non-512 byte sized sectors
>   luks2: Better error handling when setting up the cryptodisk
>   luks2: Error check segment.sector_size
>   whitespace: convert 8 spaces to tabs
>   mips: Enable __clzdi2()
>   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
>     integers
>   luks2: Use grub_log2ull to calculate log_sector_size and improve
>     readability
> 
>  grub-core/disk/cryptodisk.c        |  64 +++++++-----
>  grub-core/disk/diskfilter.c        |  12 +--
>  grub-core/disk/dmraid_nvidia.c     |   2 +-
>  grub-core/disk/efi/efidisk.c       |   2 +-
>  grub-core/disk/geli.c              |   6 +-
>  grub-core/disk/ldm.c               |   4 +-
>  grub-core/disk/luks.c              |   7 +-
>  grub-core/disk/luks2.c             | 160 +++++++++++++++++++++++------
>  grub-core/disk/mdraid1x_linux.c    |   2 +-
>  grub-core/disk/mdraid_linux.c      |   2 +-
>  grub-core/fs/cbfs.c                |  16 +--
>  grub-core/fs/nilfs2.c              |   2 +-
>  grub-core/fs/zfs/zfs.c             |   4 +-
>  grub-core/kern/compiler-rt.c       |   2 +-
>  grub-core/kern/disk.c              |   2 +-
>  grub-core/kern/mips/arc/init.c     |   2 +-
>  grub-core/normal/misc.c            |   6 +-
>  grub-core/osdep/windows/platform.c |   2 +-
>  include/grub/compiler-rt.h         |   2 +-
>  include/grub/cryptodisk.h          |   8 +-
>  include/grub/disk.h                |  21 +++-
>  include/grub/misc.h                |   7 +-
>  include/grub/types.h               |   9 ++
>  util/grub-install.c                |   2 +-
>  util/grub-probe.c                  |   2 +-
>  25 files changed, 249 insertions(+), 99 deletions(-)
> 
> Range-diff against v6:
>  -:  --------- >  1:  7e79d6fb1 disk: Rename grub_disk_get_size to grub_disk_native_sectors
>  -:  --------- >  2:  77f9671d5 misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
>  3:  8527be145 !  3:  d1a36aa79 luks2: Remove unused argument in grub_error
>     @@ Metadata
>       ## Commit message ##
>          luks2: Remove unused argument in grub_error
>      
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>     +
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
>             grub_json_getstring (&out->size, segment, "size") ||
>  -:  --------- >  4:  dab43e033 luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
>  1:  6262aefe9 !  5:  35f47644c luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
>     @@ Metadata
>      Author: Glenn Washburn <development@efficientek.com>
>      
>       ## Commit message ##
>     -    luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest
>     +    luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
>      
>          This allows code using these structs to know the named key associated with
>          these json data structures. In the future we can use these to provide better
>          error messages to the user.
>      
>     -    Get rid of idx variable in luks2_get_keyslot which was overloaded to be used
>     -    for both keyslot and segment slot keys.
>     +    Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
>     +    used for both keyslot and segment slot keys.
>      
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
>       
>       struct grub_luks2_keyslot
>       {
>     -+  grub_uint64_t slot_key;
>     ++  /* The integer key to the associative array of keyslots */
>     ++  grub_uint64_t json_slot_key;
>         grub_int64_t key_size;
>         grub_int64_t priority;
>         struct
>     @@ grub-core/disk/luks2.c: typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
>       
>       struct grub_luks2_segment
>       {
>     -+  grub_uint64_t slot_key;
>     ++  grub_uint64_t json_slot_key;
>         grub_uint64_t offset;
>         const char	*size;
>         const char	*encryption;
>     @@ grub-core/disk/luks2.c: typedef struct grub_luks2_segment grub_luks2_segment_t;
>       
>       struct grub_luks2_digest
>       {
>     -+  grub_uint64_t slot_key;
>     ++  grub_uint64_t json_slot_key;
>         /* Both keyslots and segments are interpreted as bitfields here */
>         grub_uint64_t	keyslots;
>         grub_uint64_t	segments;
>     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
>         if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>             grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
>      -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
>     -+      grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
>     ++      grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
>             grub_json_getchild (&keyslot, &keyslot, 0) ||
>             luks2_parse_keyslot (k, &keyslot))
>           return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
>     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
>         for (i = 0; i < size; i++)
>           {
>             if (grub_json_getchild (&digest, &digests, i) ||
>     -+	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
>     ++	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>                 grub_json_getchild (&digest, &digest, 0) ||
>                 luks2_parse_digest (d, &digest))
>       	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>       
>      -      if ((d->keyslots & (1 << idx)))
>     -+      if ((d->keyslots & (1 << k->slot_key)))
>     ++      if ((d->keyslots & (1 << k->json_slot_key)))
>       	break;
>           }
>         if (i == size)
>     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
>           {
>             if (grub_json_getchild (&segment, &segments, i) ||
>      -	  grub_json_getuint64 (&idx, &segment, NULL) ||
>     -+	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
>     ++	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
>       	  grub_json_getchild (&segment, &segment, 0) ||
>                 luks2_parse_segment (s, &segment))
>       	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>       
>      -      if ((d->segments & (1 << idx)))
>     -+      if ((d->segments & (1 << s->slot_key)))
>     ++      if ((d->segments & (1 << s->json_slot_key)))
>       	break;
>           }
>         if (i == size)
>  2:  3cd52834b !  6:  e52887944 luks2: Use more intuitive slot key instead of index in user messages.
>     @@ Metadata
>      Author: Glenn Washburn <development@efficientek.com>
>      
>       ## Commit message ##
>     -    luks2: Use more intuitive slot key instead of index in user messages.
>     +    luks2: Use more intuitive slot key instead of index in user messages
>      
>          Use the slot key name in the json array rather than the 0 based index in the
>          json array for keyslots, segments, and digests. This is less confusing for
>     @@ Commit message
>          messages using the index of the keyslot will mention keyslot 1 (its a
>          zero-based index). Furthermore, with this change the keyslot number will
>          align with the number used to reference the keyslot when using the
>     -    --key-slot argument to cryptsetup. Error messages now distinguish between
>     -    indexes and slot keys. The former include the string "index" in the error
>     -    string, and the later are surrounded in quotes.
>     +    --key-slot argument to cryptsetup.
>      
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>     -       grub_json_getuint64 (&k->slot_key, &keyslot, NULL) ||
>     -       grub_json_getchild (&keyslot, &keyslot, 0) ||
>     -       luks2_parse_keyslot (k, &keyslot))
>     --    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
>     -+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_idx);
>     - 
>     -   /* Get digest that matches the keyslot. */
>     -   if (grub_json_getvalue (&digests, root, "digests") ||
>     -@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>     - 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
>     + 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>                 grub_json_getchild (&digest, &digest, 0) ||
>                 luks2_parse_digest (d, &digest))
>      -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>      +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>       
>     -       if ((d->keyslots & (1 << k->slot_key)))
>     +       if ((d->keyslots & (1 << k->json_slot_key)))
>       	break;
>           }
>         if (i == size)
>     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
>         /* Get segment that matches the digest. */
>         if (grub_json_getvalue (&segments, root, "segments") ||
>      @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>     - 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
>     - 	  grub_json_getchild (&segment, &segment, 0) ||
>     -           luks2_parse_segment (s, &segment))
>     --	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>     -+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>     - 
>     -       if ((d->segments & (1 << s->slot_key)))
>       	break;
>           }
>         if (i == size)
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>             if (keyslot.priority == 0)
>       	{
>      -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
>     -+	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
>     ++	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
>       	  continue;
>               }
>       
>      -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
>     -+      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>     ++      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
>       
>             /* Set up disk according to keyslot's segment. */
>             crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       	{
>      -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
>      -			i, grub_errmsg);
>     -+	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_UINT64_T" failed: %s\n",
>     ++	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
>      +			keyslot.slot_key, grub_errmsg);
>       	  continue;
>       	}
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       	{
>      -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
>      -			i, grub_errmsg);
>     -+	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_UINT64_T": %s\n",
>     ++	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
>      +			keyslot.slot_key, grub_errmsg);
>       	  continue;
>       	}
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>              * where each element is either empty or holds a key.
>              */
>      -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
>     -+      grub_printf_ (N_("Slot %"PRIuGRUB_UINT64_T" opened\n"), keyslot.slot_key);
>     ++      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
>       
>             candidate_key_len = keyslot.key_size;
>             break;
>  4:  1a248b679 <  -:  --------- cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt
>  -:  --------- >  7:  43e3b6cce luks2: Add string "index" to user strings using a json index.
>  -:  --------- >  8:  4aa9757e1 cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
>  -:  --------- >  9:  d18993a63 cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
>  5:  45f5d644f ! 10:  7e8f242d1 luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
>     @@ Commit message
>      
>          We need to convert the sectors from the size of the underlying device to the
>          cryptodisk sector size; segment.size is in bytes which need to be converted
>     -    to cryptodisk sectors as well. And counter-intuitively, grub_disk_get_size
>     -    returns the total number of device native sectors.
>     +    to cryptodisk sectors as well.
>      
>          Also, removed an empty statement.
>      
>     -    Signed-off-by: Glenn Washburn <development@efficientek.com>
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>      
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_decrypt_key (grub_uint8_t *out_key,
>  6:  6e01cafb1 ! 11:  1fe9c38ed cryptodisk: Properly handle non-512 byte sized sectors
>     @@ Commit message
>          512 (ie the IV increments every 512 bytes). This made these changes less
>          aestetically pleasing than desired.
>      
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>     +
>       ## grub-core/disk/cryptodisk.c ##
>      @@ grub-core/disk/cryptodisk.c: lrw_xor (const struct lrw_sector *sec,
>       static gcry_err_code_t
>     @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_endecrypt (struct grub_cryptodisk *
>       	  }
>       	  break;
>       	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
>     --	  iv[1] = grub_cpu_to_le32 (sector >> 32);
>     +-	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>      -	  /* FALLTHROUGH */
>       	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
>      -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>     @@ grub-core/disk/luks.c: configure_ciphers (grub_disk_t disk, const char *check_uu
>         newdev->source_disk = NULL;
>      -  newdev->log_sector_size = 9;
>      +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
>     -   newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
>     +   newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
>         grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>         newdev->modname = "luks";
>      @@ grub-core/disk/luks.c: luks_recover_key (grub_disk_t source,
>  7:  d8927c6bc ! 12:  c9db343e8 luks2: Better error handling when setting up the cryptodisk
>     @@ Commit message
>          an invalid segment, and continue on to the next key.
>      
>       ## grub-core/disk/luks2.c ##
>     +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>     + 	break;
>     +     }
>     +   if (i == size)
>     +-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
>     ++      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key);
>     + 
>     +   /* Get segment that matches the digest. */
>     +   if (grub_json_getvalue (&segments, root, "segments") ||
>     +@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>     + 	break;
>     +     }
>     +   if (i == size)
>     +-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
>     ++    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key);
>     + 
>     +   return GRUB_ERR_NONE;
>     + }
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>             goto err;
>           }
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       
>             if (keyslot.priority == 0)
>       	{
>     -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>     +-	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
>     ++	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
>     + 	  continue;
>     +         }
>     + 
>     +-      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
>     ++      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>     + 
>     +       /* Set up disk according to keyslot's segment. */
>             crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>             crypt->log_sector_size = sizeof (unsigned int) * 8
>       		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      +				 " %"PRIuGRUB_UINT64_T" which is greater than"
>      +				 " source disk size %"PRIuGRUB_UINT64_T","
>      +				 " skipping\n",
>     -+				 segment.slot_key, crypt->offset_sectors,
>     ++				 segment.json_slot_key, crypt->offset_sectors,
>      +				 max_crypt_sectors);
>      +	  continue;
>      +	}
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>      +	{
>      +	  grub_errno = GRUB_ERR_NONE;
>     -+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>     ++	  /* Convert segment.size to sectors, rounding up to nearest sector */
>     ++	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
>     ++	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
>     ++					   1 << crypt->log_sector_size);
>     ++	  crypt->total_sectors >>= crypt->log_sector_size;
>     ++
>      +	  if (grub_errno == GRUB_ERR_NONE)
>      +	    ;
>     -+	  else if(grub_errno == GRUB_ERR_BAD_NUMBER)
>     ++	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
>      +	    {
>     -+	      /* TODO: Unparsable number-string, try to use the whole disk */
>      +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
>      +				     " \"%s\" is not a parsable number\n",
>     -+				     segment.slot_key, segment.size);
>     ++				     segment.json_slot_key, segment.size);
>      +	      continue;
>      +	    }
>     -+	  else if(grub_errno == GRUB_ERR_OUT_OF_RANGE)
>     ++	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
>      +	    {
>      +	      /*
>      +	       * There was an overflow in parsing segment.size, so disk must
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      +				     " %s overflowed 64-bit unsigned integer,"
>      +				     " the end of the crypto device will be"
>      +				     " inaccessible\n",
>     -+				     segment.slot_key, segment.size);
>     ++				     segment.json_slot_key, segment.size);
>      +	      if (crypt->total_sectors > max_crypt_sectors)
>      +		crypt->total_sectors = max_crypt_sectors;
>      +	    }
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      +	{
>      +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
>      +				 " sectors, skipping\n",
>     -+				 segment.slot_key);
>     ++				 segment.json_slot_key);
>      +	  continue;
>      +	}
>      +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      +				 " data position greater than source disk size,"
>      +				 " the end of the crypto device will be"
>      +				 " inaccessible\n",
>     -+				 segment.slot_key);
>     ++				 segment.json_slot_key);
>      +	  /* Allow decryption up to the end of the source disk. */
>      +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
>      +	}
>       
>             ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>       			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>     +       if (ret)
>     + 	{
>     + 	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
>     +-			keyslot.slot_key, grub_errmsg);
>     ++			keyslot.json_slot_key, grub_errmsg);
>     + 	  continue;
>     + 	}
>     + 
>     +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>     +       if (ret)
>     + 	{
>     + 	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
>     +-			keyslot.slot_key, grub_errmsg);
>     ++			keyslot.json_slot_key, grub_errmsg);
>     + 	  continue;
>     + 	}
>     + 
>     +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>     +        * TRANSLATORS: It's a cryptographic key slot: one element of an array
>     +        * where each element is either empty or holds a key.
>     +        */
>     +-      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
>     ++      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.json_slot_key);
>     + 
>     +       candidate_key_len = keyslot.key_size;
>     +       break;
>      
>       ## include/grub/disk.h ##
>     +@@
>     + #include <grub/device.h>
>     + /* For NULL.  */
>     + #include <grub/mm.h>
>     ++/* For ALIGN_UP.  */
>     ++#include <grub/misc.h>
>     + 
>     + /* These are used to set a device id. When you add a new disk device,
>     +    you must define a new id for it here.  */
>      @@ include/grub/disk.h: typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
>     - /* Return value of grub_disk_get_size() in case disk size is unknown. */
>     + /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
>       #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
>       
>      +/* Convert sector number from disk sized sectors to a log-size sized sector. */
>     @@ include/grub/disk.h: typedef struct grub_disk_memberlist *grub_disk_memberlist_t
>      +{
>      +  if (disk->log_sector_size < log_sector_size)
>      +    {
>     -+      /* Round up to the nearest log_sector_size sized sector. */
>     -+      sector += 1ULL << ((log_sector_size / disk->log_sector_size) - 1);
>     ++      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));
>      +      return sector >> (log_sector_size - disk->log_sector_size);
>      +    }
>      +  else
>  8:  fcd7aadb7 ! 13:  2fcef44b6 luks2: Error check segment.sector_size
>     @@ Metadata
>       ## Commit message ##
>          luks2: Error check segment.sector_size
>      
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>     +
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       
>     -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>     +       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>       
>      +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
>      +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
>     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>      +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
>      +				 " size %"PRIuGRUB_UINT64_T" is not one of"
>      +				 " 512, 1024, 2048, or 4096\n",
>     -+				 segment.slot_key, segment.sector_size);
>     ++				 segment.json_slot_key, segment.sector_size);
>      +	  continue;
>      +	}
>      +
>  9:  61f77a1a8 ! 14:  74eed4a62 whitespace: convert 8 spaces to tabs.
>     @@ Metadata
>      Author: Glenn Washburn <development@efficientek.com>
>      
>       ## Commit message ##
>     -    whitespace: convert 8 spaces to tabs.
>     +    whitespace: convert 8 spaces to tabs
>     +
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>      
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>           {
>             if (grub_json_getchild (&digest, &digests, i) ||
>     - 	  grub_json_getuint64 (&d->slot_key, &digest, NULL) ||
>     + 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>      -          grub_json_getchild (&digest, &digest, 0) ||
>      -          luks2_parse_digest (d, &digest))
>      +	  grub_json_getchild (&digest, &digest, 0) ||
>      +	  luks2_parse_digest (d, &digest))
>       	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
>       
>     -       if ((d->keyslots & (1 << k->slot_key)))
>     +       if ((d->keyslots & (1 << k->json_slot_key)))
>      @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>             if (grub_json_getchild (&segment, &segments, i) ||
>     - 	  grub_json_getuint64 (&s->slot_key, &segment, NULL) ||
>     + 	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
>       	  grub_json_getchild (&segment, &segment, 0) ||
>      -          luks2_parse_segment (s, &segment))
>      +	  luks2_parse_segment (s, &segment))
>       	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, i);
>       
>     -       if ((d->segments & (1 << s->slot_key)))
>     +       if ((d->segments & (1 << s->json_slot_key)))
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       	{
>     - 	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_UINT64_T" due to priority\n", keyslot.slot_key);
>     + 	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
>       	  continue;
>      -        }
>      +	}
>       
>     -       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_UINT64_T"\n", keyslot.slot_key);
>     +       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>       
> 10:  d71d26701 ! 15:  51c2e9160 mips: Enable __clzdi2()
>     @@ Commit message
>          __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
>          enabled.
>      
>     -    Signed-off-by: Daniel Kiper <dkiper@net-space.pl>
>     +    Suggested-by: Daniel Kiper <dkiper@net-space.pl>
>      
>       ## grub-core/kern/compiler-rt.c ##
>      @@ grub-core/kern/compiler-rt.c: __clzsi2 (grub_uint32_t val)
> 11:  8aa295f77 ! 16:  3b4ccda1f misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
>     @@ Metadata
>       ## Commit message ##
>          misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
>      
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>     +
>       ## include/grub/misc.h ##
>      @@ include/grub/misc.h: void EXPORT_FUNC(grub_real_boot_time) (const char *file,
>       #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
> 12:  7050a4ace ! 17:  8b97e6887 luks2: Use grub_log2ull to calculate log_sector_size and improve readability
>     @@ Metadata
>       ## Commit message ##
>          luks2: Use grub_log2ull to calculate log_sector_size and improve readability
>      
>     +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
>     +
>       ## grub-core/disk/luks2.c ##
>      @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
>       
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors
  2020-12-04 16:43           ` [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-12-06 19:21             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 19:21 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:40AM -0600, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
> 
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
> 
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
> 
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 50 insertions(+), 25 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 5aa0c4720..b62835acc 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>  
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>  
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t iv64;
> +
> +	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    grub_set_unaligned64 (iv, iv64);
> +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> +	      iv[1] = 0;
> +	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> +	  /* The IV is the 64 bit byte offset of the sector. */
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> -					       - dev->log_sector_size));
> -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> +					       - log_sector_size));
> +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>  				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> @@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_CBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_PCBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (err)
>  	      return err;
>  	    
> -	    for (j = 0; j < (1U << dev->log_sector_size);
> +	    for (j = 0; j < (1U << log_sector_size);
>  		 j += dev->cipher->cipher->blocksize)
>  	      {
>  		grub_crypto_xor (data + i + j, data + i + j, iv,
> @@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (do_encrypt)
>  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    else
>  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    if (err)
>  	      return err;
>  	    lrw_xor (&sec, dev, data + i);
> @@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_ECB:
>  	  if (do_encrypt)
>  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  else
>  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector)
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
>  {
> -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
>  }
>  
>  grub_err_t
> @@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
>  					size << disk->log_sector_size,
> -					sector, 0);
> +					sector, dev->log_sector_size, 0);
>    return grub_crypto_gcry_error (gcry_err);
>  }
>  
> @@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> -					sector, 1);
> +					sector, disk->log_sector_size, 1);
>    if (gcry_err)
>      {
>        grub_free (tmp);
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 5fc79d880..13103ea6a 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
> -  newdev->log_sector_size = 9;
> +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
>    newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
> @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
>  	  return err;
>  	}
>  
> -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> +					  GRUB_LUKS1_LOG_SECTOR_SIZE);
>        if (gcry_err)
>  	{
>  	  grub_free (split_key);
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index bdf40768b..de2e70796 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>        goto err;
>      }
>  
> -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> +  /*
> +   * The key slots area is always encrypted in 512-byte sectors,
> +   * regardless of encrypted data sector size.
> +   */
> +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> +				      GRUB_LUKS1_LOG_SECTOR_SIZE);
>    if (gcry_ret)
>      {
>        ret = grub_crypto_gcry_error (gcry_ret);
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index c9bf7597a..938912cf3 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -48,6 +48,12 @@ typedef enum
>  
>  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
>  
> +/* LUKS1 specification defines the block size to always be 512 bytes. */
> +#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
> +
> +/* By default dm-crypt increments the IV every 512 bytes. */
> +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> +
>  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
>  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
> @@ -144,7 +150,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector);
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size);
>  grub_err_t
>  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
>  			grub_disk_t source);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk
  2020-12-04 16:43           ` [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-12-06 19:35             ` Patrick Steinhardt
  2020-12-08  4:04               ` Glenn Washburn
  2020-12-08  4:28             ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 19:35 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:41AM -0600, Glenn Washburn wrote:
> First, check to make sure that source disk has a known size. If not, print
> debug message and return error. There are 4 cases where
> GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
> all those cases processing continues. So this is probably a bit
> conservative. However, 3 of the cases seem pathological, and the other,
> biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
> volume on a cd is a big use case, we'll error until someone complains.
> 
> Do some sanity checking on data coming from the luks header. If segment.size
> is "dynamic",

Nit: there's something missing here.

> Check for errors from grub_strtoull when converting segment size from
> string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
> not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
> returned, then there was an overflow in converting to a 64-bit unsigned
> integer. So this could be a very large disk (perhaps large raid array).
> In this case, we want to continue to try to use this key so long as the
> source disk's size is greater than this segment size. Otherwise, this is
> an invalid segment, and continue on to the next key.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 98 +++++++++++++++++++++++++++++++++++++-----
>  include/grub/disk.h    | 17 ++++++++
>  2 files changed, 105 insertions(+), 10 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index de2e70796..1bb3a333d 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key);
>  
>    return GRUB_ERR_NONE;
>  }
> @@ -600,37 +600,115 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>  
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
> +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> +			     "conservatively returning error\n", source->name);
> +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> +      typeof(source->total_sectors) max_crypt_sectors = 0;

Please bear with me if this has been discussed in a previous round, but
why exactly do we cast `max_crypt_sectors` to the type of
`source->total_sectors`? And isn't the variable always set anyway in
case the keyslot has a non-zero priority?

Patrick

> +
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
>        if (ret)
>  	goto err;
> +      if (grub_errno != GRUB_ERR_NONE)
> +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
> +	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
>  	  continue;
>          }
>  
> -      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
> +      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      /* Set to the source disk size, which is the maximum we allow. */
> +      max_crypt_sectors = grub_disk_convert_sector(source,
> +						   source->total_sectors,
> +						   crypt->log_sector_size);
> +
> +      if (max_crypt_sectors < crypt->offset_sectors)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
> +				 " %"PRIuGRUB_UINT64_T" which is greater than"
> +				 " source disk size %"PRIuGRUB_UINT64_T","
> +				 " skipping\n",
> +				 segment.json_slot_key, crypt->offset_sectors,
> +				 max_crypt_sectors);
> +	  continue;
> +	}
> +
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	{
> +	  grub_errno = GRUB_ERR_NONE;
> +	  /* Convert segment.size to sectors, rounding up to nearest sector */
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
> +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> +					   1 << crypt->log_sector_size);
> +	  crypt->total_sectors >>= crypt->log_sector_size;
> +
> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;
> +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> +	    {
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " \"%s\" is not a parsable number\n",
> +				     segment.json_slot_key, segment.size);
> +	      continue;
> +	    }
> +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /*
> +	       * There was an overflow in parsing segment.size, so disk must
> +	       * be very large or the string is incorrect.
> +	       */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " %s overflowed 64-bit unsigned integer,"
> +				     " the end of the crypto device will be"
> +				     " inaccessible\n",
> +				     segment.json_slot_key, segment.size);
> +	      if (crypt->total_sectors > max_crypt_sectors)
> +		crypt->total_sectors = max_crypt_sectors;
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
> +				 " sectors, skipping\n",
> +				 segment.json_slot_key);
> +	  continue;
> +	}
> +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
> +				 " data position greater than source disk size,"
> +				 " the end of the crypto device will be"
> +				 " inaccessible\n",
> +				 segment.json_slot_key);
> +	  /* Allow decryption up to the end of the source disk. */
> +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
> +	}
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
>  	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> -			keyslot.slot_key, grub_errmsg);
> +			keyslot.json_slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -638,7 +716,7 @@ luks2_recover_key (grub_disk_t source,
>        if (ret)
>  	{
>  	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
> -			keyslot.slot_key, grub_errmsg);
> +			keyslot.json_slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -646,7 +724,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
> +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.json_slot_key);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index 0fb727d3d..f9227f285 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -27,6 +27,8 @@
>  #include <grub/device.h>
>  /* For NULL.  */
>  #include <grub/mm.h>
> +/* For ALIGN_UP.  */
> +#include <grub/misc.h>
>  
>  /* These are used to set a device id. When you add a new disk device,
>     you must define a new id for it here.  */
> @@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
>  /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
>  #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
>  
> +/* Convert sector number from disk sized sectors to a log-size sized sector. */
> +static inline grub_disk_addr_t
> +grub_disk_convert_sector (grub_disk_t disk,
> +			  grub_disk_addr_t sector,
> +			  grub_size_t log_sector_size)
> +{
> +  if (disk->log_sector_size < log_sector_size)
> +    {
> +      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));
> +      return sector >> (log_sector_size - disk->log_sector_size);
> +    }
> +  else
> +    return sector << (disk->log_sector_size - log_sector_size);
> +}
> +
>  /* Convert to GRUB native disk sized sector from disk sized sector. */
>  static inline grub_disk_addr_t
>  grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 13/17] luks2: Error check segment.sector_size
  2020-12-04 16:43           ` [PATCH v7 13/17] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-12-06 19:35             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 19:35 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:42AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 1bb3a333d..499c9330b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -629,6 +629,17 @@ luks2_recover_key (grub_disk_t source,
>  
>        grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
>  
> +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
> +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
> +	    segment.sector_size == 2048 || segment.sector_size == 4096))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
> +				 " size %"PRIuGRUB_UINT64_T" is not one of"
> +				 " 512, 1024, 2048, or 4096\n",
> +				 segment.json_slot_key, segment.sector_size);
> +	  continue;
> +	}
> +
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 15/17] mips: Enable __clzdi2()
  2020-12-04 16:43           ` [PATCH v7 15/17] mips: Enable __clzdi2() Glenn Washburn
@ 2020-12-06 19:36             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 19:36 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:44AM -0600, Glenn Washburn wrote:
> This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
> __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
> enabled.
> 
> Suggested-by: Daniel Kiper <dkiper@net-space.pl>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

I'm not going to give my Reviewed-by on this patch as I honestly ain't
got a clue if those are supported on MIPS. So I don't feel qualified to.

Patrick

> ---
>  grub-core/kern/compiler-rt.c | 2 +-
>  include/grub/compiler-rt.h   | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
> index a464200c6..2057c2e0c 100644
> --- a/grub-core/kern/compiler-rt.c
> +++ b/grub-core/kern/compiler-rt.c
> @@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
>  }
>  #endif
>  
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  __clzdi2 (grub_uint64_t val)
>  {
> diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
> index 7591980b4..17828b322 100644
> --- a/include/grub/compiler-rt.h
> +++ b/include/grub/compiler-rt.h
> @@ -115,7 +115,7 @@ int
>  EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
>  #endif
>  
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
>  #endif
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-12-04 16:43           ` [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
@ 2020-12-06 19:44             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-06 19:44 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Fri, Dec 04, 2020 at 10:43:46AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 2335ded77..4fa5a0dbc 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -642,8 +642,7 @@ luks2_recover_key (grub_disk_t source,
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> -      crypt->log_sector_size = sizeof (unsigned int) * 8
> -		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      crypt->log_sector_size = grub_log2ull (segment.sector_size);

I was quite confused by the fact that previously we were using an
unsigned int (which typically is 4 bytes on 64 bit systems), but now
we're using the 8 byte wide uint64. Until I realized that
`grub_log2ull(n)` uses `__builtin_clzll` instead of `__builtin_clz`. A
commit message would've helped to clear up this confusion.

Other than that:

Reviewed-by: Patrick Steinhardt <ps@pks.im>

>        /* Set to the source disk size, which is the maximum we allow. */
>        max_crypt_sectors = grub_disk_convert_sector(source,
>  						   source->total_sectors,
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors
  2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
  2020-12-06 13:24             ` Patrick Steinhardt
@ 2020-12-07 19:38             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 19:38 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt, Daniel Kiper

On Fri, Dec 04, 2020 at 10:43:30AM -0600, Glenn Washburn wrote:
> The function grub_disk_get_size is confusingly named because it actually
> returns a sector count where the sectors are sized in the grub native sector
> size. Rename to something more appropriate.
>
> Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
>

Nit, please do not leave empty lines between the tags.
I will fix it before committing.

> Signed-off-by: Glenn Washburn <development@efficientek.com>

Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  2020-12-04 16:43           ` [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
  2020-12-06 13:24             ` Patrick Steinhardt
@ 2020-12-07 19:50             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 19:50 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:31AM -0600, Glenn Washburn wrote:
> This ensures that expected order of operations is preserved when arguments
> are expressions.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Good catch! Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 03/17] luks2: Remove unused argument in grub_error
  2020-12-04 16:43           ` [PATCH v7 03/17] luks2: Remove unused argument in grub_error Glenn Washburn
  2020-12-06 13:25             ` Patrick Steinhardt
@ 2020-12-07 19:52             ` Daniel Kiper
  2020-12-08 17:45               ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 19:52 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt, Daniel Kiper

On Fri, Dec 04, 2020 at 10:43:32AM -0600, Glenn Washburn wrote:
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Nit, my RB should be after your SOB. I will fix it.

Daniel


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

* Re: [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
  2020-12-04 16:43           ` [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
  2020-12-06 13:26             ` Patrick Steinhardt
@ 2020-12-07 19:58             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 19:58 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:33AM -0600, Glenn Washburn wrote:
> We should assume that the output argument "out" is uninitialized and could
> have random data. So, make sure to initialize the segments and keyslots bit
> fields because potentially not all bits of those fields are written to.
> Otherwise, the digest could say it belongs to keyslots and segments that it
> does not.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-06 13:29             ` Patrick Steinhardt
@ 2020-12-07 20:02               ` Daniel Kiper
  2020-12-08  4:06                 ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 20:02 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Glenn Washburn, grub-devel

On Sun, Dec 06, 2020 at 02:29:06PM +0100, Patrick Steinhardt wrote:
> On Fri, Dec 04, 2020 at 10:43:34AM -0600, Glenn Washburn wrote:
> > This allows code using these structs to know the named key associated with
> > these json data structures. In the future we can use these to provide better
> > error messages to the user.
> >
> > Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
> > used for both keyslot and segment slot keys.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
>
> Personally, I'd have named them `json_slot_idx`. But you've already done
> so much work on improving the code that I don't want this to be the
> reason to not give an SOB, especially considering that it's a strict
> improvement anyway. So:
>
> Signed-off-by: Patrick Steinhardt <ps@pks.im>

I can change this to json_slot_idx before committing if Glenn does not
object. Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages
  2020-12-04 16:43           ` [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
  2020-12-06 13:31             ` Patrick Steinhardt
@ 2020-12-07 20:15             ` Daniel Kiper
  2020-12-08 17:56               ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 20:15 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:35AM -0600, Glenn Washburn wrote:
> Use the slot key name in the json array rather than the 0 based index in the
> json array for keyslots, segments, and digests. This is less confusing for
> the end user. For example, say you have a LUKS2 device with a key in slot 1
> and slot 4. When using the password for slot 4 to unlock the device, the
> messages using the index of the keyslot will mention keyslot 1 (its a
> zero-based index). Furthermore, with this change the keyslot number will
> align with the number used to reference the keyslot when using the
> --key-slot argument to cryptsetup.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 437c1da07..ea1065bcf 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -284,13 +284,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
>            grub_json_getchild (&digest, &digest, 0) ||
>            luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);

Does not this change belong to next patch?

>        if ((d->keyslots & (1 << k->json_slot_key)))
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);

I am afraid this does not build. The slot_key seems a remnant from v6.

>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);

Ditto and below...

>    return GRUB_ERR_NONE;
>  }
> @@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
>
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
>  	  continue;
>          }
>
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
>
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -623,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
> +			keyslot.slot_key, grub_errmsg);
>  	  continue;
>  	}
>
> @@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
>
>        candidate_key_len = keyslot.key_size;
>        break;

Daniel


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

* Re: [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index.
  2020-12-04 16:43           ` [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index Glenn Washburn
  2020-12-06 13:31             ` Patrick Steinhardt
@ 2020-12-07 20:17             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 20:17 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:36AM -0600, Glenn Washburn wrote:
> This allows error messages to be more easily distinguishable between indexes
> and slot keys. The former include the string "index" in the error/debug
> string, and the later are surrounded in quotes.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-04 16:43           ` [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
  2020-12-06 13:32             ` Patrick Steinhardt
@ 2020-12-07 20:18             ` Daniel Kiper
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 20:18 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:37AM -0600, Glenn Washburn wrote:
> The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
> type.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-04 16:43           ` [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
  2020-12-06 13:33             ` Patrick Steinhardt
@ 2020-12-07 20:22             ` Daniel Kiper
  2020-12-08  4:06               ` Glenn Washburn
  1 sibling, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-07 20:22 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 04, 2020 at 10:43:38AM -0600, Glenn Washburn wrote:
> Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> unsigned number with size of type.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

But one nit below...

> ---
>  grub-core/disk/cryptodisk.c | 8 ++++----
>  include/grub/types.h        | 7 +++++++
>  2 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 0e955a020..5aa0c4720 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
>  					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
>  	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 9989e3a16..0542011cc 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
>  #endif
>  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
>
> +/*
> +  Cast to unsigned long long so that the "return value" is always a consistent
> +  type and to ensure an unsigned value regardless of type parameter.
> + */

Incorrect comment formatting...

> +#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
> +#define GRUB_TYPE_U_MIN(type) 0ULL
> +
>  typedef grub_uint64_t grub_properly_aligned_t;
>
>  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]

Daniel


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

* Re: [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk
  2020-12-06 19:35             ` Patrick Steinhardt
@ 2020-12-08  4:04               ` Glenn Washburn
  2020-12-08  6:41                 ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08  4:04 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Daniel Kiper

On Sun, 6 Dec 2020 20:35:13 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Fri, Dec 04, 2020 at 10:43:41AM -0600, Glenn Washburn wrote:
> > First, check to make sure that source disk has a known size. If
> > not, print debug message and return error. There are 4 cases where
> > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > uboot), and in all those cases processing continues. So this is
> > probably a bit conservative. However, 3 of the cases seem
> > pathological, and the other, biosdisk, happens when booting from a
> > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > case, we'll error until someone complains.
> > 
> > Do some sanity checking on data coming from the luks header. If
> > segment.size is "dynamic",
> 
> Nit: there's something missing here.

Yep, thanks for catching that. I was going to complete this and forgot
in my rush to get the series out before some travel.  I'll rework that.

> > Check for errors from grub_strtoull when converting segment size
> > from string. If a GRUB_ERR_BAD_NUMBER error was returned, then the
> > string was not a valid parsable number, so skip the key. If
> > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow in
> > converting to a 64-bit unsigned integer. So this could be a very
> > large disk (perhaps large raid array). In this case, we want to
> > continue to try to use this key so long as the source disk's size
> > is greater than this segment size. Otherwise, this is an invalid
> > segment, and continue on to the next key.
> > 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 98
> > +++++++++++++++++++++++++++++++++++++----- include/grub/disk.h    |
> > 17 ++++++++ 2 files changed, 105 insertions(+), 10 deletions(-)
> > 
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index de2e70796..1bb3a333d 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s break;
> >      }
> >    if (i == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key); 
> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> > @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s break;
> >      }
> >    if (i == size)
> > -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> > +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key); 
> >    return GRUB_ERR_NONE;
> >  }
> > @@ -600,37 +600,115 @@ luks2_recover_key (grub_disk_t source,
> >        goto err;
> >      }
> >  
> > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > +    {
> > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > in read. */
> > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > +			     "conservatively returning error\n",
> > source->name);
> > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > source device");
> > +      goto err;
> > +    }
> > +
> >    /* Try all keyslot */
> >    for (i = 0; i < size; i++)
> >      {
> > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> 
> Please bear with me if this has been discussed in a previous round,
> but why exactly do we cast `max_crypt_sectors` to the type of
> `source->total_sectors`?

Technically, this isn't a cast.  Its a variable declaration.  But I'm
using the typeof(source->total_sectors) because max_crypt_sectors can
be no more or less than the total sectors, ie its of the same type.

> And isn't the variable always set anyway in
> case the keyslot has a non-zero priority?

Yep. Are you suggesting that it need not be initialized?  This is true,
but I don't think that's a problem.  I think generally initializing
things is a good practice.  It might be problematic if this was in an
oft used function (or it might not, would need to see if the compiler
was smart enough to ignore the initialization).  But that
initialization is going to happen very rarely in the lifetime of a grub
execution instance.  I also don't really care either way.

Glenn

> Patrick
>
> > +
> > +      grub_errno = GRUB_ERR_NONE;
> >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > i); if (ret)
> >  	goto err;
> > +      if (grub_errno != GRUB_ERR_NONE)
> > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> > luks2_get_keyslot\n", grub_errno); 
> >        if (keyslot.priority == 0)
> >  	{
> > -	  grub_dprintf ("luks2", "Ignoring keyslot
> > \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
> > +	  grub_dprintf ("luks2", "Ignoring keyslot
> > \"%"PRIuGRUB_UINT64_T"\" due to priority\n",
> > keyslot.json_slot_key); continue; }
> >  
> > -      grub_dprintf ("luks2", "Trying keyslot
> > \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
> > +      grub_dprintf ("luks2", "Trying keyslot
> > \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key); 
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > (unsigned int) * 8
> >  		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1;
> > +      /* Set to the source disk size, which is the maximum we
> > allow. */
> > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > +
> > source->total_sectors,
> > +
> > crypt->log_sector_size); +
> > +      if (max_crypt_sectors < crypt->offset_sectors)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has offset"
> > +				 " %"PRIuGRUB_UINT64_T" which is
> > greater than"
> > +				 " source disk size
> > %"PRIuGRUB_UINT64_T","
> > +				 " skipping\n",
> > +				 segment.json_slot_key,
> > crypt->offset_sectors,
> > +				 max_crypt_sectors);
> > +	  continue;
> > +	}
> > +
> >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> > -			       - crypt->offset_sectors;
> > +	crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors; else
> > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size;
> > +	{
> > +	  grub_errno = GRUB_ERR_NONE;
> > +	  /* Convert segment.size to sectors, rounding up to
> > nearest sector */
> > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > NULL, 10);
> > +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> > +					   1 <<
> > crypt->log_sector_size);
> > +	  crypt->total_sectors >>= crypt->log_sector_size;
> > +
> > +	  if (grub_errno == GRUB_ERR_NONE)
> > +	    ;
> > +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> > +	    {
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " \"%s\" is not a parsable
> > number\n",
> > +				     segment.json_slot_key,
> > segment.size);
> > +	      continue;
> > +	    }
> > +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > +	    {
> > +	      /*
> > +	       * There was an overflow in parsing segment.size, so
> > disk must
> > +	       * be very large or the string is incorrect.
> > +	       */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " %s overflowed 64-bit
> > unsigned integer,"
> > +				     " the end of the crypto
> > device will be"
> > +				     " inaccessible\n",
> > +				     segment.json_slot_key,
> > segment.size);
> > +	      if (crypt->total_sectors > max_crypt_sectors)
> > +		crypt->total_sectors = max_crypt_sectors;
> > +	    }
> > +	}
> > +
> > +      if (crypt->total_sectors == 0)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has zero"
> > +				 " sectors, skipping\n",
> > +				 segment.json_slot_key);
> > +	  continue;
> > +	}
> > +      else if (max_crypt_sectors < (crypt->offset_sectors +
> > crypt->total_sectors))
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has last"
> > +				 " data position greater than
> > source disk size,"
> > +				 " the end of the crypto device
> > will be"
> > +				 " inaccessible\n",
> > +				 segment.json_slot_key);
> > +	  /* Allow decryption up to the end of the source disk. */
> > +	  crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors;
> > +	}
> >  
> >        ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> >  	  grub_dprintf ("luks2", "Decryption with keyslot
> > \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> > -			keyslot.slot_key, grub_errmsg);
> > +			keyslot.json_slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> > @@ -638,7 +716,7 @@ luks2_recover_key (grub_disk_t source,
> >        if (ret)
> >  	{
> >  	  grub_dprintf ("luks2", "Could not open keyslot
> > \"%"PRIuGRUB_UINT64_T"\": %s\n",
> > -			keyslot.slot_key, grub_errmsg);
> > +			keyslot.json_slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >  
> > @@ -646,7 +724,7 @@ luks2_recover_key (grub_disk_t source,
> >         * TRANSLATORS: It's a cryptographic key slot: one element
> > of an array
> >         * where each element is either empty or holds a key.
> >         */
> > -      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"),
> > keyslot.slot_key);
> > +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"),
> > keyslot.json_slot_key); 
> >        candidate_key_len = keyslot.key_size;
> >        break;
> > diff --git a/include/grub/disk.h b/include/grub/disk.h
> > index 0fb727d3d..f9227f285 100644
> > --- a/include/grub/disk.h
> > +++ b/include/grub/disk.h
> > @@ -27,6 +27,8 @@
> >  #include <grub/device.h>
> >  /* For NULL.  */
> >  #include <grub/mm.h>
> > +/* For ALIGN_UP.  */
> > +#include <grub/misc.h>
> >  
> >  /* These are used to set a device id. When you add a new disk
> > device, you must define a new id for it here.  */
> > @@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist
> > *grub_disk_memberlist_t; /* Return value of
> > grub_disk_native_sectors() in case disk size is unknown. */ #define
> > GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL 
> > +/* Convert sector number from disk sized sectors to a log-size
> > sized sector. */ +static inline grub_disk_addr_t
> > +grub_disk_convert_sector (grub_disk_t disk,
> > +			  grub_disk_addr_t sector,
> > +			  grub_size_t log_sector_size)
> > +{
> > +  if (disk->log_sector_size < log_sector_size)
> > +    {
> > +      sector = ALIGN_UP (sector, 1 << (log_sector_size /
> > disk->log_sector_size));
> > +      return sector >> (log_sector_size - disk->log_sector_size);
> > +    }
> > +  else
> > +    return sector << (disk->log_sector_size - log_sector_size);
> > +}
> > +
> >  /* Convert to GRUB native disk sized sector from disk sized
> > sector. */ static inline grub_disk_addr_t
> >  grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t
> > sector) -- 
> > 2.27.0
> > 


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

* Re: [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-07 20:22             ` Daniel Kiper
@ 2020-12-08  4:06               ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08  4:06 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Mon, 7 Dec 2020 21:22:09 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Dec 04, 2020 at 10:43:38AM -0600, Glenn Washburn wrote:
> > Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for
> > an unsigned number with size of type.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> 
> But one nit below...
> 
> > ---
> >  grub-core/disk/cryptodisk.c | 8 ++++----
> >  include/grub/types.h        | 7 +++++++
> >  2 files changed, 11 insertions(+), 4 deletions(-)
> >
> > diff --git a/grub-core/disk/cryptodisk.c
> > b/grub-core/disk/cryptodisk.c index 0e955a020..5aa0c4720 100644
> > --- a/grub-core/disk/cryptodisk.c
> > +++ b/grub-core/disk/cryptodisk.c
> > @@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct
> > grub_cryptodisk *dev, iv[1] = grub_cpu_to_le32 (sector >>
> > GRUB_TYPE_BITS (iv[0])); /* FALLTHROUGH */
> >  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> >  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS
> > (iv[1])
> >  					       -
> > dev->log_sector_size)); iv[0] = grub_cpu_to_le32 ((sector <<
> > dev->log_sector_size)
> > -				    & 0xFFFFFFFF);
> > +				    & GRUB_TYPE_U_MAX (iv[0]));
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> >  	  {
> >  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> >  	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS
> > (iv[0]));
> > -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> > +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX
> > (iv[0])); }
> >  	  break;
> >  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> > -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> > +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX
> > (iv[0])); err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
> >  					 dev->cipher->cipher->blocksize);
> >  	  if (err)
> > diff --git a/include/grub/types.h b/include/grub/types.h
> > index 9989e3a16..0542011cc 100644
> > --- a/include/grub/types.h
> > +++ b/include/grub/types.h
> > @@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
> >  #endif
> >  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
> >
> > +/*
> > +  Cast to unsigned long long so that the "return value" is always
> > a consistent
> > +  type and to ensure an unsigned value regardless of type
> > parameter.
> > + */
> 
> Incorrect comment formatting...

I'll fix it, and get it right one of these days.

> > +#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof
> > (type))(~0))) +#define GRUB_TYPE_U_MIN(type) 0ULL
> > +
> >  typedef grub_uint64_t grub_properly_aligned_t;
> >
> >  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size)
> > grub_properly_aligned_t name[((size) + sizeof
> > (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
> 
> Daniel


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

* Re: [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-07 20:02               ` Daniel Kiper
@ 2020-12-08  4:06                 ` Glenn Washburn
  2020-12-08  6:38                   ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08  4:06 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: Patrick Steinhardt, grub-devel

On Mon, 7 Dec 2020 21:02:39 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Sun, Dec 06, 2020 at 02:29:06PM +0100, Patrick Steinhardt wrote:
> > On Fri, Dec 04, 2020 at 10:43:34AM -0600, Glenn Washburn wrote:
> > > This allows code using these structs to know the named key
> > > associated with these json data structures. In the future we can
> > > use these to provide better error messages to the user.
> > >
> > > Get rid of idx variable in luks2_get_keyslot() which was
> > > overloaded to be used for both keyslot and segment slot keys.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> >
> > Personally, I'd have named them `json_slot_idx`. But you've already
> > done so much work on improving the code that I don't want this to
> > be the reason to not give an SOB, especially considering that it's
> > a strict improvement anyway. So:
> >
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> 
> I can change this to json_slot_idx before committing if Glenn does not
> object. Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Thanks Patrick for the sentiment.  Looking at the luks2 spec, it says:

"JSON  objects  must  have  their names  formatted  as  a  string  that
represents  a  number  in  the  decimal  notation (unsigned integer) –
for example ”0”, ”1” and must contain attribute _type_. According  to
the _type_,  the  implementation  decides  how  to  handle  (or
ignore) such an object.  This notation allows mapping to LUKS1 API
functions that use an integer as a reference to keyslots objects."

So here, the spec is calling that value a "name", and saying that it
must be a string of decimal digits.  Looking at the spec, the "name" of
the keyslot object does not need to correspond to the index into the
array of keyslot areas on disk.  However it does in the canonical
implementation for use with LUKS1 API functions which require and
integer, as suggested in the quote above.

I'd say that these numbers are actually an id for the object of its
respective class.  In the cryptsetup implementation, the "id" happens
to correspond to the index into the binary key area array, but that's
needn't be the case. My preference would be to name it "id" and second
choice would be just "idx" (since its usually an index into a physical
array of key areas or virtual array of segments and digests).

I don't think the "json" part of the name is warranted, because it
really has nothing to do with json.  The "slot" part is really only
applicable to keyslots because digests and segments don't have an
equivalent slot aspect.  So I suggest we name the struct member names
to just "id" instead.  And where we just the index of the name-value
pair in the json associative array we use "json_idx" as a suffix.  So
this would mean changing the argument keyslot_idx in
luks2_get_keyslot() to keyslot_json_idx. Optionally the local variable
"i" in luks2_get_keyslot() and luks2_parse_segment() could be renamed
to "json_idx" as well (I don't care either way about this though).

Glenn


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

* Re: [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk
  2020-12-04 16:43           ` [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
  2020-12-06 19:35             ` Patrick Steinhardt
@ 2020-12-08  4:28             ` Glenn Washburn
  1 sibling, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08  4:28 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper

This patch got mangled accidentally with patch 5.  I'll update them
both.

Glenn

On Fri,  4 Dec 2020 10:43:41 -0600
Glenn Washburn <development@efficientek.com> wrote:

> First, check to make sure that source disk has a known size. If not,
> print debug message and return error. There are 4 cases where
> GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot),
> and in all those cases processing continues. So this is probably a bit
> conservative. However, 3 of the cases seem pathological, and the
> other, biosdisk, happens when booting from a cd. Since I doubt
> booting from a LUKS2 volume on a cd is a big use case, we'll error
> until someone complains.
> 
> Do some sanity checking on data coming from the luks header. If
> segment.size is "dynamic",
> 
> Check for errors from grub_strtoull when converting segment size from
> string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string
> was not a valid parsable number, so skip the key. If
> GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow in
> converting to a 64-bit unsigned integer. So this could be a very
> large disk (perhaps large raid array). In this case, we want to
> continue to try to use this key so long as the source disk's size is
> greater than this segment size. Otherwise, this is an invalid
> segment, and continue on to the next key.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 98
> +++++++++++++++++++++++++++++++++++++----- include/grub/disk.h    |
> 17 ++++++++ 2 files changed, 105 insertions(+), 10 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index de2e70796..1bb3a333d 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> grub_luks2_digest_t *d, grub_luks2_s break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key); 
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> grub_luks2_digest_t *d, grub_luks2_s break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key); 
>    return GRUB_ERR_NONE;
>  }
> @@ -600,37 +600,115 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>  
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      /* FIXME: Allow use of source disk, and maybe cause errors in
> read. */
> +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> +			     "conservatively returning error\n",
> source->name);
> +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source
> device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (i = 0; i < size; i++)
>      {
> +      typeof(source->total_sectors) max_crypt_sectors = 0;
> +
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
>        if (ret)
>  	goto err;
> +      if (grub_errno != GRUB_ERR_NONE)
> +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> luks2_get_keyslot\n", grub_errno); 
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot
> \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
> +	  grub_dprintf ("luks2", "Ignoring keyslot
> \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
> continue; }
>  
> -      grub_dprintf ("luks2", "Trying keyslot
> \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
> +      grub_dprintf ("luks2", "Trying keyslot
> \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key); 
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset,
> segment.sector_size, NULL); crypt->log_sector_size = sizeof (unsigned
> int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size)
> - 1;
> +      /* Set to the source disk size, which is the maximum we allow.
> */
> +      max_crypt_sectors = grub_disk_convert_sector(source,
> +
> source->total_sectors,
> +
> crypt->log_sector_size); +
> +      if (max_crypt_sectors < crypt->offset_sectors)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> has offset"
> +				 " %"PRIuGRUB_UINT64_T" which is
> greater than"
> +				 " source disk size
> %"PRIuGRUB_UINT64_T","
> +				 " skipping\n",
> +				 segment.json_slot_key,
> crypt->offset_sectors,
> +				 max_crypt_sectors);
> +	  continue;
> +	}
> +
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >>
> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	crypt->total_sectors = max_crypt_sectors -
> crypt->offset_sectors; else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> 10) >> crypt->log_sector_size;
> +	{
> +	  grub_errno = GRUB_ERR_NONE;
> +	  /* Convert segment.size to sectors, rounding up to nearest
> sector */
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL,
> 10);
> +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> +					   1 <<
> crypt->log_sector_size);
> +	  crypt->total_sectors >>= crypt->log_sector_size;
> +
> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;
> +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> +	    {
> +	      grub_dprintf ("luks2", "Segment
> \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " \"%s\" is not a parsable
> number\n",
> +				     segment.json_slot_key,
> segment.size);
> +	      continue;
> +	    }
> +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /*
> +	       * There was an overflow in parsing segment.size, so
> disk must
> +	       * be very large or the string is incorrect.
> +	       */
> +	      grub_dprintf ("luks2", "Segment
> \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " %s overflowed 64-bit unsigned
> integer,"
> +				     " the end of the crypto device
> will be"
> +				     " inaccessible\n",
> +				     segment.json_slot_key,
> segment.size);
> +	      if (crypt->total_sectors > max_crypt_sectors)
> +		crypt->total_sectors = max_crypt_sectors;
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> has zero"
> +				 " sectors, skipping\n",
> +				 segment.json_slot_key);
> +	  continue;
> +	}
> +      else if (max_crypt_sectors < (crypt->offset_sectors +
> crypt->total_sectors))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> has last"
> +				 " data position greater than source
> disk size,"
> +				 " the end of the crypto device will
> be"
> +				 " inaccessible\n",
> +				 segment.json_slot_key);
> +	  /* Allow decryption up to the end of the source disk. */
> +	  crypt->total_sectors = max_crypt_sectors -
> crypt->offset_sectors;
> +	}
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt,
> &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> (passphrase)); if (ret)
>  	{
>  	  grub_dprintf ("luks2", "Decryption with keyslot
> \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> -			keyslot.slot_key, grub_errmsg);
> +			keyslot.json_slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -638,7 +716,7 @@ luks2_recover_key (grub_disk_t source,
>        if (ret)
>  	{
>  	  grub_dprintf ("luks2", "Could not open keyslot
> \"%"PRIuGRUB_UINT64_T"\": %s\n",
> -			keyslot.slot_key, grub_errmsg);
> +			keyslot.json_slot_key, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -646,7 +724,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of
> an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"),
> keyslot.slot_key);
> +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"),
> keyslot.json_slot_key); 
>        candidate_key_len = keyslot.key_size;
>        break;
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index 0fb727d3d..f9227f285 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -27,6 +27,8 @@
>  #include <grub/device.h>
>  /* For NULL.  */
>  #include <grub/mm.h>
> +/* For ALIGN_UP.  */
> +#include <grub/misc.h>
>  
>  /* These are used to set a device id. When you add a new disk device,
>     you must define a new id for it here.  */
> @@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist
> *grub_disk_memberlist_t; /* Return value of
> grub_disk_native_sectors() in case disk size is unknown. */ #define
> GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL 
> +/* Convert sector number from disk sized sectors to a log-size sized
> sector. */ +static inline grub_disk_addr_t
> +grub_disk_convert_sector (grub_disk_t disk,
> +			  grub_disk_addr_t sector,
> +			  grub_size_t log_sector_size)
> +{
> +  if (disk->log_sector_size < log_sector_size)
> +    {
> +      sector = ALIGN_UP (sector, 1 << (log_sector_size /
> disk->log_sector_size));
> +      return sector >> (log_sector_size - disk->log_sector_size);
> +    }
> +  else
> +    return sector << (disk->log_sector_size - log_sector_size);
> +}
> +
>  /* Convert to GRUB native disk sized sector from disk sized sector.
> */ static inline grub_disk_addr_t
>  grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t
> sector)


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

* Re: [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-08  4:06                 ` Glenn Washburn
@ 2020-12-08  6:38                   ` Patrick Steinhardt
  2020-12-08 17:55                     ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-08  6:38 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: Daniel Kiper, grub-devel

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

On Mon, Dec 07, 2020 at 10:06:44PM -0600, Glenn Washburn wrote:
> On Mon, 7 Dec 2020 21:02:39 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
> 
> > On Sun, Dec 06, 2020 at 02:29:06PM +0100, Patrick Steinhardt wrote:
> > > On Fri, Dec 04, 2020 at 10:43:34AM -0600, Glenn Washburn wrote:
> > > > This allows code using these structs to know the named key
> > > > associated with these json data structures. In the future we can
> > > > use these to provide better error messages to the user.
> > > >
> > > > Get rid of idx variable in luks2_get_keyslot() which was
> > > > overloaded to be used for both keyslot and segment slot keys.
> > > >
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > >
> > > Personally, I'd have named them `json_slot_idx`. But you've already
> > > done so much work on improving the code that I don't want this to
> > > be the reason to not give an SOB, especially considering that it's
> > > a strict improvement anyway. So:
> > >
> > > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > 
> > I can change this to json_slot_idx before committing if Glenn does not
> > object. Otherwise Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> 
> Thanks Patrick for the sentiment.  Looking at the luks2 spec, it says:
> 
> "JSON  objects  must  have  their names  formatted  as  a  string  that
> represents  a  number  in  the  decimal  notation (unsigned integer) –
> for example ”0”, ”1” and must contain attribute _type_. According  to
> the _type_,  the  implementation  decides  how  to  handle  (or
> ignore) such an object.  This notation allows mapping to LUKS1 API
> functions that use an integer as a reference to keyslots objects."
> 
> So here, the spec is calling that value a "name", and saying that it
> must be a string of decimal digits.  Looking at the spec, the "name" of
> the keyslot object does not need to correspond to the index into the
> array of keyslot areas on disk.  However it does in the canonical
> implementation for use with LUKS1 API functions which require and
> integer, as suggested in the quote above.
> 
> I'd say that these numbers are actually an id for the object of its
> respective class.  In the cryptsetup implementation, the "id" happens
> to correspond to the index into the binary key area array, but that's
> needn't be the case. My preference would be to name it "id" and second
> choice would be just "idx" (since its usually an index into a physical
> array of key areas or virtual array of segments and digests).
> 
> I don't think the "json" part of the name is warranted, because it
> really has nothing to do with json.  The "slot" part is really only
> applicable to keyslots because digests and segments don't have an
> equivalent slot aspect.  So I suggest we name the struct member names
> to just "id" instead.  And where we just the index of the name-value
> pair in the json associative array we use "json_idx" as a suffix.  So
> this would mean changing the argument keyslot_idx in
> luks2_get_keyslot() to keyslot_json_idx. Optionally the local variable
> "i" in luks2_get_keyslot() and luks2_parse_segment() could be renamed
> to "json_idx" as well (I don't care either way about this though).
> 
> Glenn

Sounds sensible to me. Based on your reasoning, I'm happy with either
"id" or "key". So we may just as well just keep it as-is, as you prefer.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk
  2020-12-08  4:04               ` Glenn Washburn
@ 2020-12-08  6:41                 ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-08  6:41 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Mon, Dec 07, 2020 at 10:04:01PM -0600, Glenn Washburn wrote:
> On Sun, 6 Dec 2020 20:35:13 +0100
> Patrick Steinhardt <ps@pks.im> wrote:
> 
> > On Fri, Dec 04, 2020 at 10:43:41AM -0600, Glenn Washburn wrote:
> > > First, check to make sure that source disk has a known size. If
> > > not, print debug message and return error. There are 4 cases where
> > > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > > uboot), and in all those cases processing continues. So this is
> > > probably a bit conservative. However, 3 of the cases seem
> > > pathological, and the other, biosdisk, happens when booting from a
> > > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > > case, we'll error until someone complains.
> > > 
> > > Do some sanity checking on data coming from the luks header. If
> > > segment.size is "dynamic",
> > 
> > Nit: there's something missing here.
> 
> Yep, thanks for catching that. I was going to complete this and forgot
> in my rush to get the series out before some travel.  I'll rework that.
> 
> > > Check for errors from grub_strtoull when converting segment size
> > > from string. If a GRUB_ERR_BAD_NUMBER error was returned, then the
> > > string was not a valid parsable number, so skip the key. If
> > > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow in
> > > converting to a 64-bit unsigned integer. So this could be a very
> > > large disk (perhaps large raid array). In this case, we want to
> > > continue to try to use this key so long as the source disk's size
> > > is greater than this segment size. Otherwise, this is an invalid
> > > segment, and continue on to the next key.
> > > 
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 98
> > > +++++++++++++++++++++++++++++++++++++----- include/grub/disk.h    |
> > > 17 ++++++++ 2 files changed, 105 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index de2e70796..1bb3a333d 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > > grub_luks2_digest_t *d, grub_luks2_s break;
> > >      }
> > >    if (i == size)
> > > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> > > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key); 
> > >    /* Get segment that matches the digest. */
> > >    if (grub_json_getvalue (&segments, root, "segments") ||
> > > @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > > grub_luks2_digest_t *d, grub_luks2_s break;
> > >      }
> > >    if (i == size)
> > > -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > > digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> > > +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > > digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key); 
> > >    return GRUB_ERR_NONE;
> > >  }
> > > @@ -600,37 +600,115 @@ luks2_recover_key (grub_disk_t source,
> > >        goto err;
> > >      }
> > >  
> > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > +    {
> > > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > > in read. */
> > > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > > +			     "conservatively returning error\n",
> > > source->name);
> > > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > > source device");
> > > +      goto err;
> > > +    }
> > > +
> > >    /* Try all keyslot */
> > >    for (i = 0; i < size; i++)
> > >      {
> > > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > 
> > Please bear with me if this has been discussed in a previous round,
> > but why exactly do we cast `max_crypt_sectors` to the type of
> > `source->total_sectors`?
> 
> Technically, this isn't a cast.  Its a variable declaration.  But I'm
> using the typeof(source->total_sectors) because max_crypt_sectors can
> be no more or less than the total sectors, ie its of the same type.

Oh, of course. I somehow didn't realize this at all, probably because
this is not something one sees that often.

> > And isn't the variable always set anyway in
> > case the keyslot has a non-zero priority?
> 
> Yep. Are you suggesting that it need not be initialized?  This is true,
> but I don't think that's a problem.  I think generally initializing
> things is a good practice.  It might be problematic if this was in an
> oft used function (or it might not, would need to see if the compiler
> was smart enough to ignore the initialization).  But that
> initialization is going to happen very rarely in the lifetime of a grub
> execution instance.  I also don't really care either way.
> 
> Glenn

I just didn't realize it's a declaration, so keeping the initialization
is fine.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v7 03/17] luks2: Remove unused argument in grub_error
  2020-12-07 19:52             ` Daniel Kiper
@ 2020-12-08 17:45               ` Glenn Washburn
  2020-12-08 18:32                 ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 17:45 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt, Daniel Kiper

On Mon, 7 Dec 2020 20:52:44 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Dec 04, 2020 at 10:43:32AM -0600, Glenn Washburn wrote:
> > Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> 
> Nit, my RB should be after your SOB. I will fix it.
> 
> Daniel

This is annoying to do with how my git is setup, which is to
automatically append my SOB when doing format-patch.  Do you just do
SOBs and RBs by hand, or have a way to do this more automatically?

Glenn


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

* Re: [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
  2020-12-08  6:38                   ` Patrick Steinhardt
@ 2020-12-08 17:55                     ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 17:55 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: Daniel Kiper, grub-devel

On Tue, 8 Dec 2020 07:38:31 +0100
Patrick Steinhardt <ps@pks.im> wrote:

> On Mon, Dec 07, 2020 at 10:06:44PM -0600, Glenn Washburn wrote:
> > On Mon, 7 Dec 2020 21:02:39 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> > 
> > > On Sun, Dec 06, 2020 at 02:29:06PM +0100, Patrick Steinhardt
> > > wrote:
> > > > On Fri, Dec 04, 2020 at 10:43:34AM -0600, Glenn Washburn wrote:
> > > > > This allows code using these structs to know the named key
> > > > > associated with these json data structures. In the future we
> > > > > can use these to provide better error messages to the user.
> > > > >
> > > > > Get rid of idx variable in luks2_get_keyslot() which was
> > > > > overloaded to be used for both keyslot and segment slot keys.
> > > > >
> > > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > >
> > > > Personally, I'd have named them `json_slot_idx`. But you've
> > > > already done so much work on improving the code that I don't
> > > > want this to be the reason to not give an SOB, especially
> > > > considering that it's a strict improvement anyway. So:
> > > >
> > > > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > > 
> > > I can change this to json_slot_idx before committing if Glenn
> > > does not object. Otherwise Reviewed-by: Daniel Kiper
> > > <daniel.kiper@oracle.com>
> > 
> > Thanks Patrick for the sentiment.  Looking at the luks2 spec, it
> > says:
> > 
> > "JSON  objects  must  have  their names  formatted  as  a  string
> > that represents  a  number  in  the  decimal  notation (unsigned
> > integer) – for example ”0”, ”1” and must contain attribute _type_.
> > According  to the _type_,  the  implementation  decides  how  to
> > handle  (or ignore) such an object.  This notation allows mapping
> > to LUKS1 API functions that use an integer as a reference to
> > keyslots objects."
> > 
> > So here, the spec is calling that value a "name", and saying that it
> > must be a string of decimal digits.  Looking at the spec, the
> > "name" of the keyslot object does not need to correspond to the
> > index into the array of keyslot areas on disk.  However it does in
> > the canonical implementation for use with LUKS1 API functions which
> > require and integer, as suggested in the quote above.
> > 
> > I'd say that these numbers are actually an id for the object of its
> > respective class.  In the cryptsetup implementation, the "id"
> > happens to correspond to the index into the binary key area array,
> > but that's needn't be the case. My preference would be to name it
> > "id" and second choice would be just "idx" (since its usually an
> > index into a physical array of key areas or virtual array of
> > segments and digests).
> > 
> > I don't think the "json" part of the name is warranted, because it
> > really has nothing to do with json.  The "slot" part is really only
> > applicable to keyslots because digests and segments don't have an
> > equivalent slot aspect.  So I suggest we name the struct member
> > names to just "id" instead.  And where we just the index of the
> > name-value pair in the json associative array we use "json_idx" as
> > a suffix.  So this would mean changing the argument keyslot_idx in
> > luks2_get_keyslot() to keyslot_json_idx. Optionally the local
> > variable "i" in luks2_get_keyslot() and luks2_parse_segment() could
> > be renamed to "json_idx" as well (I don't care either way about
> > this though).
> > 
> > Glenn
> 
> Sounds sensible to me. Based on your reasoning, I'm happy with either
> "id" or "key". So we may just as well just keep it as-is, as you
> prefer.
> 
> Patrick

On third thought, while I like "id" better because its really a generic
id, we use it as an index into the segments and keyslots bitfield of
the grub_luks2_digest_t struct. So I'm going to I'm going to choose idx
instead of id.  If the implementation changes and we choose to support
arbitrary object names we can change the member name to something more
generic.

Glenn


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

* Re: [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages
  2020-12-07 20:15             ` Daniel Kiper
@ 2020-12-08 17:56               ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 17:56 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Mon, 7 Dec 2020 21:15:33 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Dec 04, 2020 at 10:43:35AM -0600, Glenn Washburn wrote:
> > Use the slot key name in the json array rather than the 0 based
> > index in the json array for keyslots, segments, and digests. This
> > is less confusing for the end user. For example, say you have a
> > LUKS2 device with a key in slot 1 and slot 4. When using the
> > password for slot 4 to unlock the device, the messages using the
> > index of the keyslot will mention keyslot 1 (its a zero-based
> > index). Furthermore, with this change the keyslot number will align
> > with the number used to reference the keyslot when using the
> > --key-slot argument to cryptsetup.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 20 ++++++++++----------
> >  1 file changed, 10 insertions(+), 10 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 437c1da07..ea1065bcf 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -284,13 +284,13 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s grub_json_getuint64
> > (&d->json_slot_key, &digest, NULL) || grub_json_getchild (&digest,
> > &digest, 0) || luks2_parse_digest (d, &digest))
> > -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > digest %"PRIuGRUB_SIZE, i);
> > +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse
> > digest index %"PRIuGRUB_SIZE, i);
> 
> Does not this change belong to next patch?

Ugh, yes.

> >        if ((d->keyslots & (1 << k->json_slot_key)))
> >  	break;
> >      }
> >    if (i == size)
> > -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> > +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for
> > keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
> 
> I am afraid this does not build. The slot_key seems a remnant from v6.

Hmm, yes, I'm fairly certain the whole patch series builds, which is
why I didn't catch this.  Some changes got applied to the wrong
patches, which is why this happened, I think.

> >    /* Get segment that matches the digest. */
> >    if (grub_json_getvalue (&segments, root, "segments") ||
> > @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
> > grub_luks2_digest_t *d, grub_luks2_s break;
> >      }
> >    if (i == size)
> > -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest %"PRIuGRUB_SIZE);
> > +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for
> > digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
> 
> Ditto and below...
>
> >    return GRUB_ERR_NONE;
> >  }
> > @@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
> >
> >        if (keyslot.priority == 0)
> >  	{
> > -	  grub_dprintf ("luks2", "Ignoring keyslot
> > %"PRIuGRUB_SIZE" due to priority\n", i);
> > +	  grub_dprintf ("luks2", "Ignoring keyslot
> > \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
> > continue; }
> >
> > -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n",
> > i);
> > +      grub_dprintf ("luks2", "Trying keyslot
> > \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
> >
> >        /* Set up disk according to keyslot's segment. */
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); @@ -623,16 +623,16 @@ luks2_recover_key
> > (grub_disk_t source, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Decryption with keyslot
> > %"PRIuGRUB_SIZE" failed: %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Decryption with keyslot
> > \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >
> >        ret = luks2_verify_key (&digest, candidate_key,
> > keyslot.key_size); if (ret)
> >  	{
> > -	  grub_dprintf ("luks2", "Could not open keyslot
> > %"PRIuGRUB_SIZE": %s\n",
> > -			i, grub_errmsg);
> > +	  grub_dprintf ("luks2", "Could not open keyslot
> > \"%"PRIuGRUB_UINT64_T"\": %s\n",
> > +			keyslot.slot_key, grub_errmsg);
> >  	  continue;
> >  	}
> >
> > @@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
> >         * TRANSLATORS: It's a cryptographic key slot: one element
> > of an array
> >         * where each element is either empty or holds a key.
> >         */
> > -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> > +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"),
> > keyslot.slot_key);
> >
> >        candidate_key_len = keyslot.key_size;
> >        break;
> 
> Daniel

Glenn


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

* Re: [PATCH v7 03/17] luks2: Remove unused argument in grub_error
  2020-12-08 17:45               ` Glenn Washburn
@ 2020-12-08 18:32                 ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-08 18:32 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: Daniel Kiper, grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 11:45:37AM -0600, Glenn Washburn wrote:
> On Mon, 7 Dec 2020 20:52:44 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
> 
> > On Fri, Dec 04, 2020 at 10:43:32AM -0600, Glenn Washburn wrote:
> > > Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > 
> > Nit, my RB should be after your SOB. I will fix it.
> > 
> > Daniel
> 
> This is annoying to do with how my git is setup, which is to
> automatically append my SOB when doing format-patch.  Do you just do
> SOBs and RBs by hand, or have a way to do this more automatically?
> 
> Glenn

You can for example just use `git commit --signoff` when creating the
commit. There's also `git rebase --signoff` to add SOBs for rebased
patches if they don't have one yet. If RBs come in during review, I
typically just `git rebase --interactive` and `r` commits to add the
trailing RBs.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
                           ` (18 preceding siblings ...)
  2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
@ 2020-12-08 22:45         ` Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
                             ` (18 more replies)
  19 siblings, 19 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch series, fixes issues with v7 series. Some of those patches had
changes applied to the wrong patch. The added structure member was renamed
again, this time to idx. And there is an added patch that renames some json
index variables to note that they are such. 

Glenn

Glenn Washburn (18):
  disk: Rename grub_disk_get_size to grub_disk_native_sectors
  misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  whitespace: convert 8 spaces to tabs
  luks2: Remove unused argument in grub_error
  luks2: Make sure all fields of output argument in luks2_parse_digest()
    are written to
  luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
  luks2: Use more intuitive object name instead of json index in user
    messages
  luks2: Rename json index variables to names that they are obviously
    json indexes
  luks2: Add string "index" to user strings using a json index.
  cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  luks2: grub_cryptodisk_t->total_sectors is the max number of device
    native sectors
  cryptodisk: Properly handle non-512 byte sized sectors
  luks2: Better error handling when setting up the cryptodisk
  luks2: Error check segment.sector_size
  mips: Enable __clzdi2()
  misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
    integers
  luks2: Use grub_log2ull to calculate log_sector_size and improve
    readability

 grub-core/disk/cryptodisk.c        |  64 ++++++----
 grub-core/disk/diskfilter.c        |  12 +-
 grub-core/disk/dmraid_nvidia.c     |   2 +-
 grub-core/disk/efi/efidisk.c       |   2 +-
 grub-core/disk/geli.c              |   6 +-
 grub-core/disk/ldm.c               |   4 +-
 grub-core/disk/luks.c              |   7 +-
 grub-core/disk/luks2.c             | 184 ++++++++++++++++++++++-------
 grub-core/disk/mdraid1x_linux.c    |   2 +-
 grub-core/disk/mdraid_linux.c      |   2 +-
 grub-core/fs/cbfs.c                |  16 +--
 grub-core/fs/nilfs2.c              |   2 +-
 grub-core/fs/zfs/zfs.c             |   4 +-
 grub-core/kern/compiler-rt.c       |   2 +-
 grub-core/kern/disk.c              |   2 +-
 grub-core/kern/mips/arc/init.c     |   2 +-
 grub-core/normal/misc.c            |   6 +-
 grub-core/osdep/windows/platform.c |   2 +-
 include/grub/compiler-rt.h         |   2 +-
 include/grub/cryptodisk.h          |   8 +-
 include/grub/disk.h                |  21 +++-
 include/grub/misc.h                |   7 +-
 include/grub/types.h               |   9 ++
 util/grub-install.c                |   2 +-
 util/grub-probe.c                  |   2 +-
 25 files changed, 261 insertions(+), 111 deletions(-)

Range-diff against v7:
 1:  a80929b15 !  1:  f4062e4f6 disk: Rename grub_disk_get_size to grub_disk_native_sectors
    @@ Commit message
         size. Rename to something more appropriate.
     
         Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +    Reviewed-by: Patrick Steinhardt <ps@pks.im>
     
      ## grub-core/disk/diskfilter.c ##
     @@ grub-core/disk/diskfilter.c: scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
 2:  d4b462fd3 !  2:  17b1ef195 misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
    @@ Commit message
         This ensures that expected order of operations is preserved when arguments
         are expressions.
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +    Reviewed-by: Patrick Steinhardt <ps@pks.im>
    +
      ## include/grub/misc.h ##
     @@
      #include <grub/compiler.h>
 -:  --------- >  3:  eb8625d9f whitespace: convert 8 spaces to tabs
 3:  d1a23ff0a !  4:  0f28628e2 luks2: Remove unused argument in grub_error
    @@ Commit message
         luks2: Remove unused argument in grub_error
     
         Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +    Reviewed-by: Patrick Steinhardt <ps@pks.im>
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
 4:  61fcebc1a !  5:  705548bc2 luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
    @@ Commit message
         Otherwise, the digest could say it belongs to keyslots and segments that it
         does not.
     
    +    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    +    Reviewed-by: Patrick Steinhardt <ps@pks.im>
    +
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
          return grub_error (GRUB_ERR_BAD_ARGUMENT,
 5:  f6a6befdb !  6:  56d4c397a luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest
    +    luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
     
         This allows code using these structs to know the named key associated with
         these json data structures. In the future we can use these to provide better
         error messages to the user.
     
    -    Get rid of idx variable in luks2_get_keyslot() which was overloaded to be
    -    used for both keyslot and segment slot keys.
    +    Get rid of idx local variable in luks2_get_keyslot() which was overloaded to
    +    be used for both keyslot and segment slot keys.
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_header grub_luks2_header_t;
      struct grub_luks2_keyslot
      {
     +  /* The integer key to the associative array of keyslots */
    -+  grub_uint64_t json_slot_key;
    ++  grub_uint64_t idx;
        grub_int64_t key_size;
        grub_int64_t priority;
        struct
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
      
      struct grub_luks2_segment
      {
    -+  grub_uint64_t json_slot_key;
    ++  grub_uint64_t idx;
        grub_uint64_t offset;
        const char	*size;
        const char	*encryption;
    @@ grub-core/disk/luks2.c: typedef struct grub_luks2_segment grub_luks2_segment_t;
      
      struct grub_luks2_digest
      {
    -+  grub_uint64_t json_slot_key;
    ++  grub_uint64_t idx;
        /* Both keyslots and segments are interpreted as bitfields here */
        grub_uint64_t	keyslots;
        grub_uint64_t	segments;
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
        if (grub_json_getvalue (&keyslots, root, "keyslots") ||
            grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
     -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
    -+      grub_json_getuint64 (&k->json_slot_key, &keyslot, NULL) ||
    ++      grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
            grub_json_getchild (&keyslot, &keyslot, 0) ||
            luks2_parse_keyslot (k, &keyslot))
          return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
        for (i = 0; i < size; i++)
          {
            if (grub_json_getchild (&digest, &digests, i) ||
    -+	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
    -           grub_json_getchild (&digest, &digest, 0) ||
    -           luks2_parse_digest (d, &digest))
    ++	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
    + 	  grub_json_getchild (&digest, &digest, 0) ||
    + 	  luks2_parse_digest (d, &digest))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
      
     -      if ((d->keyslots & (1 << idx)))
    -+      if ((d->keyslots & (1 << k->json_slot_key)))
    ++      if ((d->keyslots & (1 << k->idx)))
      	break;
          }
        if (i == size)
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
          {
            if (grub_json_getchild (&segment, &segments, i) ||
     -	  grub_json_getuint64 (&idx, &segment, NULL) ||
    -+	  grub_json_getuint64 (&s->json_slot_key, &segment, NULL) ||
    ++	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
      	  grub_json_getchild (&segment, &segment, 0) ||
    -           luks2_parse_segment (s, &segment))
    + 	  luks2_parse_segment (s, &segment))
      	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
      
     -      if ((d->segments & (1 << idx)))
    -+      if ((d->segments & (1 << s->json_slot_key)))
    ++      if ((d->segments & (1 << s->idx)))
      	break;
          }
        if (i == size)
 6:  5c53328e4 !  7:  1991eca5a luks2: Use more intuitive slot key instead of index in user messages
    @@ Metadata
     Author: Glenn Washburn <development@efficientek.com>
     
      ## Commit message ##
    -    luks2: Use more intuitive slot key instead of index in user messages
    +    luks2: Use more intuitive object name instead of json index in user messages
     
    -    Use the slot key name in the json array rather than the 0 based index in the
    +    Use the object name in the json array rather than the 0 based index in the
         json array for keyslots, segments, and digests. This is less confusing for
         the end user. For example, say you have a LUKS2 device with a key in slot 1
         and slot 4. When using the password for slot 4 to unlock the device, the
    @@ Commit message
     
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - 	  grub_json_getuint64 (&d->json_slot_key, &digest, NULL) ||
    -           grub_json_getchild (&digest, &digest, 0) ||
    -           luks2_parse_digest (d, &digest))
    --	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
    -+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, i);
    - 
    -       if ((d->keyslots & (1 << k->json_slot_key)))
      	break;
          }
        if (i == size)
     -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
    -+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
    ++      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->idx);
      
        /* Get segment that matches the digest. */
        if (grub_json_getvalue (&segments, root, "segments") ||
    @@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_d
          }
        if (i == size)
     -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
    -+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
    ++    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->idx);
      
        return GRUB_ERR_NONE;
      }
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            if (keyslot.priority == 0)
      	{
     -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
    -+	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
    ++	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.idx);
      	  continue;
    -         }
    + 	}
      
     -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
    -+      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
    ++      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
      
            /* Set up disk according to keyslot's segment. */
            crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
     -			i, grub_errmsg);
     +	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
    -+			keyslot.slot_key, grub_errmsg);
    ++			keyslot.idx, grub_errmsg);
      	  continue;
      	}
      
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
     -			i, grub_errmsg);
     +	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
    -+			keyslot.slot_key, grub_errmsg);
    ++			keyslot.idx, grub_errmsg);
      	  continue;
      	}
      
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
             * where each element is either empty or holds a key.
             */
     -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
    -+      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
    ++      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.idx);
      
            candidate_key_len = keyslot.key_size;
            break;
 7:  a4e5e65de <  -:  --------- luks2: Add string "index" to user strings using a json index.
 -:  --------- >  8:  c1af2d286 luks2: Rename json index variables to names that they are obviously json indexes
 -:  --------- >  9:  984166770 luks2: Add string "index" to user strings using a json index.
 8:  d143d8eac = 10:  acc4a205c cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
 9:  905cb3912 ! 11:  c39083e56 cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
    @@ include/grub/types.h: typedef grub_int32_t	grub_ssize_t;
      # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
      
     +/*
    -+  Cast to unsigned long long so that the "return value" is always a consistent
    -+  type and to ensure an unsigned value regardless of type parameter.
    ++ * Cast to unsigned long long so that the "return value" is always a consistent
    ++ * type and to ensure an unsigned value regardless of type parameter.
     + */
     +#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
     +#define GRUB_TYPE_U_MIN(type) 0ULL
10:  5dfb095fd = 12:  dee584996 luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
11:  78949263b = 13:  06cd1951f cryptodisk: Properly handle non-512 byte sized sectors
12:  f4277024e ! 14:  9fbd815f9 luks2: Better error handling when setting up the cryptodisk
    @@ Commit message
         volume on a cd is a big use case, we'll error until someone complains.
     
         Do some sanity checking on data coming from the luks header. If segment.size
    -    is "dynamic",
    -
    -    Check for errors from grub_strtoull when converting segment size from
    +    is "dynamic", verify that the offset is not past the end of disk. Otherwise,
    +    check for errors from grub_strtoull when converting segment size from
         string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
         not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
         returned, then there was an overflow in converting to a 64-bit unsigned
         integer. So this could be a very large disk (perhaps large raid array).
    -    In this case, we want to continue to try to use this key so long as the
    -    source disk's size is greater than this segment size. Otherwise, this is
    -    an invalid segment, and continue on to the next key.
    +    In this case, we want to continue to try to use this key, but only allow
    +    access up to the end of the source disk.
     
      ## grub-core/disk/luks2.c ##
    -@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - 	break;
    -     }
    -   if (i == size)
    --      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->slot_key);
    -+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->json_slot_key);
    - 
    -   /* Get segment that matches the digest. */
    -   if (grub_json_getvalue (&segments, root, "segments") ||
    -@@ grub-core/disk/luks2.c: luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
    - 	break;
    -     }
    -   if (i == size)
    --    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->slot_key);
    -+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->json_slot_key);
    - 
    -   return GRUB_ERR_NONE;
    - }
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            goto err;
          }
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +    }
     +
        /* Try all keyslot */
    -   for (i = 0; i < size; i++)
    +   for (json_idx = 0; json_idx < size; json_idx++)
          {
     +      typeof(source->total_sectors) max_crypt_sectors = 0;
     +
     +      grub_errno = GRUB_ERR_NONE;
    -       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
    +       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
            if (ret)
      	goto err;
     +      if (grub_errno != GRUB_ERR_NONE)
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
            if (keyslot.priority == 0)
      	{
    --	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.slot_key);
    -+	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.json_slot_key);
    - 	  continue;
    -         }
    - 
    --      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.slot_key);
    -+      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
    - 
    -       /* Set up disk according to keyslot's segment. */
    +@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
            crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
            crypt->log_sector_size = sizeof (unsigned int) * 8
      		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				 " %"PRIuGRUB_UINT64_T" which is greater than"
     +				 " source disk size %"PRIuGRUB_UINT64_T","
     +				 " skipping\n",
    -+				 segment.json_slot_key, crypt->offset_sectors,
    ++				 segment.idx, crypt->offset_sectors,
     +				 max_crypt_sectors);
     +	  continue;
     +	}
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	    {
     +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
     +				     " \"%s\" is not a parsable number\n",
    -+				     segment.json_slot_key, segment.size);
    ++				     segment.idx, segment.size);
     +	      continue;
     +	    }
     +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				     " %s overflowed 64-bit unsigned integer,"
     +				     " the end of the crypto device will be"
     +				     " inaccessible\n",
    -+				     segment.json_slot_key, segment.size);
    ++				     segment.idx, segment.size);
     +	      if (crypt->total_sectors > max_crypt_sectors)
     +		crypt->total_sectors = max_crypt_sectors;
     +	    }
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	{
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
     +				 " sectors, skipping\n",
    -+				 segment.json_slot_key);
    ++				 segment.idx);
     +	  continue;
     +	}
     +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +				 " data position greater than source disk size,"
     +				 " the end of the crypto device will be"
     +				 " inaccessible\n",
    -+				 segment.json_slot_key);
    ++				 segment.idx);
     +	  /* Allow decryption up to the end of the source disk. */
     +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
     +	}
      
            ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
      			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
    -       if (ret)
    - 	{
    - 	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
    --			keyslot.slot_key, grub_errmsg);
    -+			keyslot.json_slot_key, grub_errmsg);
    - 	  continue;
    - 	}
    - 
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    -       if (ret)
    - 	{
    - 	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
    --			keyslot.slot_key, grub_errmsg);
    -+			keyslot.json_slot_key, grub_errmsg);
    - 	  continue;
    - 	}
    - 
    -@@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
    -        * TRANSLATORS: It's a cryptographic key slot: one element of an array
    -        * where each element is either empty or holds a key.
    -        */
    --      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.slot_key);
    -+      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.json_slot_key);
    - 
    -       candidate_key_len = keyslot.key_size;
    -       break;
     
      ## include/grub/disk.h ##
     @@
13:  65255f2d4 ! 15:  09c5b15f3 luks2: Error check segment.sector_size
    @@ Metadata
      ## Commit message ##
         luks2: Error check segment.sector_size
     
    -    Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
    -
      ## grub-core/disk/luks2.c ##
     @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
      
    -       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.json_slot_key);
    +       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
      
     +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
     +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
    @@ grub-core/disk/luks2.c: luks2_recover_key (grub_disk_t source,
     +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
     +				 " size %"PRIuGRUB_UINT64_T" is not one of"
     +				 " 512, 1024, 2048, or 4096\n",
    -+				 segment.json_slot_key, segment.sector_size);
    ++				 segment.idx, segment.sector_size);
     +	  continue;
     +	}
     +
14:  20357ebd6 <  -:  --------- whitespace: convert 8 spaces to tabs
15:  600b89d70 = 16:  60e37ca9f mips: Enable __clzdi2()
16:  a2d394c95 = 17:  302862ec1 misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
17:  68e0dac97 = 18:  baa1de127 luks2: Use grub_log2ull to calculate log_sector_size and improve readability
-- 
2.27.0



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

* [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 17:39             ` Daniel Kiper
  2020-12-08 22:45           ` [PATCH v8 02/18] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
                             ` (17 subsequent siblings)
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

The function grub_disk_get_size is confusingly named because it actually
returns a sector count where the sectors are sized in the grub native sector
size. Rename to something more appropriate.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/diskfilter.c        | 12 ++++++------
 grub-core/disk/dmraid_nvidia.c     |  2 +-
 grub-core/disk/efi/efidisk.c       |  2 +-
 grub-core/disk/geli.c              |  6 +++---
 grub-core/disk/ldm.c               |  4 ++--
 grub-core/disk/luks.c              |  2 +-
 grub-core/disk/mdraid1x_linux.c    |  2 +-
 grub-core/disk/mdraid_linux.c      |  2 +-
 grub-core/fs/cbfs.c                | 16 ++++++++--------
 grub-core/fs/nilfs2.c              |  2 +-
 grub-core/fs/zfs/zfs.c             |  4 ++--
 grub-core/kern/disk.c              |  2 +-
 grub-core/kern/mips/arc/init.c     |  2 +-
 grub-core/normal/misc.c            |  6 +++---
 grub-core/osdep/windows/platform.c |  2 +-
 include/grub/disk.h                |  4 ++--
 util/grub-install.c                |  2 +-
 util/grub-probe.c                  |  2 +-
 18 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 86557f923..032011566 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -148,7 +148,7 @@ scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
 	if (m->disk && m->disk->id == disk->id
 	    && m->disk->dev->id == disk->dev->id
 	    && m->part_start == grub_partition_get_start (disk->partition)
-	    && m->part_size == grub_disk_get_size (disk))
+	    && m->part_size == grub_disk_native_sectors (disk))
 	  return 0;
     }
 
@@ -1190,13 +1190,13 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 
   grub_dprintf ("diskfilter", "Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name,
 		(unsigned long long) grub_partition_get_start (disk->partition),
-		(unsigned long long) grub_disk_get_size (disk),
+		(unsigned long long) grub_disk_native_sectors (disk),
 		array->name, diskfilter->name);
 #ifdef GRUB_UTIL
   grub_util_info ("Inserting %s (+%" GRUB_HOST_PRIuLONG_LONG ",%"
 		  GRUB_HOST_PRIuLONG_LONG ") into %s (%s)\n", disk->name,
 		  (unsigned long long) grub_partition_get_start (disk->partition),
-		  (unsigned long long) grub_disk_get_size (disk),
+		  (unsigned long long) grub_disk_native_sectors (disk),
 		  array->name, diskfilter->name);
   array->driver = diskfilter;
 #endif
@@ -1210,7 +1210,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 	struct grub_diskfilter_lv *lv;
 	/* FIXME: Check whether the update time of the superblocks are
 	   the same.  */
-	if (pv->disk && grub_disk_get_size (disk) >= pv->part_size)
+	if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size)
 	  return GRUB_ERR_NONE;
 	pv->disk = grub_disk_open (disk->name);
 	if (!pv->disk)
@@ -1219,7 +1219,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id,
 	   raid device, we shouldn't change it.  */
 	pv->start_sector -= pv->part_start;
 	pv->part_start = grub_partition_get_start (disk->partition);
-	pv->part_size = grub_disk_get_size (disk);
+	pv->part_size = grub_disk_native_sectors (disk);
 
 #ifdef GRUB_UTIL
 	{
@@ -1311,7 +1311,7 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk,
 	if (pv->disk && pv->disk->id == disk->id
 	    && pv->disk->dev->id == disk->dev->id
 	    && pv->part_start == grub_partition_get_start (disk->partition)
-	    && pv->part_size == grub_disk_get_size (disk))
+	    && pv->part_size == grub_disk_native_sectors (disk))
 	  {
 	    if (vg_out)
 	      *vg_out = vg;
diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c
index 060279124..4d2fb04d1 100644
--- a/grub-core/disk/dmraid_nvidia.c
+++ b/grub-core/disk/dmraid_nvidia.c
@@ -107,7 +107,7 @@ grub_dmraid_nv_detect (grub_disk_t disk,
     /* Skip partition.  */
     return NULL;
 
-  sector = grub_disk_get_size (disk);
+  sector = grub_disk_native_sectors (disk);
   if (sector == GRUB_DISK_SIZE_UNKNOWN)
     /* Not raid.  */
     return NULL;
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index 9e20af70e..f077b5f55 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -867,7 +867,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       if (ctx.hd->partition_start == 0
 	  && (ctx.hd->partition_size << (parent->log_sector_size
 					 - GRUB_DISK_SECTOR_BITS))
-	  == grub_disk_get_size (parent))
+	  == grub_disk_native_sectors (parent))
 	{
 	  dev_name = grub_strdup (parent->name);
 	}
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 0175ce4c4..2f34a35e6 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -258,7 +258,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
     return NULL;
 
-  sector = grub_disk_get_size (disk);
+  sector = grub_disk_native_sectors (disk);
   if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
     return NULL;
 
@@ -391,7 +391,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
 
   newdev->modname = "geli";
 
-  newdev->total_sectors = grub_disk_get_size (disk) - 1;
+  newdev->total_sectors = grub_disk_native_sectors (disk) - 1;
   grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
   COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
   return newdev;
@@ -420,7 +420,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
   if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
     return grub_error (GRUB_ERR_BUG, "mdlen is too long");
 
-  sector = grub_disk_get_size (source);
+  sector = grub_disk_native_sectors (source);
   if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
     return grub_error (GRUB_ERR_BUG, "not a geli");
 
diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
index 58f8a53e1..912e88255 100644
--- a/grub-core/disk/ldm.c
+++ b/grub-core/disk/ldm.c
@@ -821,7 +821,7 @@ grub_ldm_detect (grub_disk_t disk,
 	    /* LDM is never inside a partition.  */
 	    if (!has_ldm || disk->partition)
 	      continue;
-	    sector = grub_disk_get_size (disk);
+	    sector = grub_disk_native_sectors (disk);
 	    if (sector == GRUB_DISK_SIZE_UNKNOWN)
 	      continue;
 	    sector--;
@@ -938,7 +938,7 @@ grub_util_is_ldm (grub_disk_t disk)
 	  /* LDM is never inside a partition.  */
 	  if (!has_ldm || disk->partition)
 	    continue;
-	  sector = grub_disk_get_size (disk);
+	  sector = grub_disk_native_sectors (disk);
 	  if (sector == GRUB_DISK_SIZE_UNKNOWN)
 	    continue;
 	  sector--;
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index aa9877b68..5fc79d880 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -125,7 +125,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
   newdev->log_sector_size = 9;
-  newdev->total_sectors = grub_disk_get_size (disk) - newdev->offset_sectors;
+  newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
 
diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c
index c980feba4..38444b02c 100644
--- a/grub-core/disk/mdraid1x_linux.c
+++ b/grub-core/disk/mdraid1x_linux.c
@@ -111,7 +111,7 @@ grub_mdraid_detect (grub_disk_t disk,
   grub_uint64_t size;
   grub_uint8_t minor_version;
 
-  size = grub_disk_get_size (disk);
+  size = grub_disk_native_sectors (disk);
 
   /* Check for an 1.x superblock.
    * It's always aligned to a 4K boundary
diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c
index 11024ae31..e40216f51 100644
--- a/grub-core/disk/mdraid_linux.c
+++ b/grub-core/disk/mdraid_linux.c
@@ -190,7 +190,7 @@ grub_mdraid_detect (grub_disk_t disk,
   struct grub_diskfilter_vg *ret;
 
   /* The sector where the mdraid 0.90 superblock is stored, if available.  */
-  size = grub_disk_get_size (disk);
+  size = grub_disk_native_sectors (disk);
   if (size == GRUB_DISK_SIZE_UNKNOWN)
     /* not 0.9x raid.  */
     return NULL;
diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c
index 857bea991..581215ef1 100644
--- a/grub-core/fs/cbfs.c
+++ b/grub-core/fs/cbfs.c
@@ -148,16 +148,16 @@ grub_cbfs_mount (grub_disk_t disk)
   grub_off_t header_off;
   struct cbfs_header head;
 
-  if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN)
+  if (grub_disk_native_sectors (disk) == GRUB_DISK_SIZE_UNKNOWN)
     goto fail;
 
-  if (grub_disk_read (disk, grub_disk_get_size (disk) - 1,
+  if (grub_disk_read (disk, grub_disk_native_sectors (disk) - 1,
 		      GRUB_DISK_SECTOR_SIZE - sizeof (ptr),
 		      sizeof (ptr), &ptr))
     goto fail;
 
   ptr = grub_cpu_to_le32 (ptr);
-  header_off = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  header_off = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     + (grub_int32_t) ptr;
 
   if (grub_disk_read (disk, 0, header_off,
@@ -171,16 +171,16 @@ grub_cbfs_mount (grub_disk_t disk)
   if (!data)
     goto fail;
 
-  data->cbfs_start = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  data->cbfs_start = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset));
-  data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS)
+  data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)
     - grub_be_to_cpu32 (head.bootblocksize);
   data->cbfs_align = grub_be_to_cpu32 (head.align);
 
-  if (data->cbfs_start >= (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
+  if (data->cbfs_start >= (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
     goto fail;
-  if (data->cbfs_end > (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS))
-    data->cbfs_end = (grub_disk_get_size (disk) << GRUB_DISK_SECTOR_BITS);
+  if (data->cbfs_end > (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS))
+    data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS);
 
   data->next_hofs = data->cbfs_start;
 
diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c
index 7ed148d3b..082326f38 100644
--- a/grub-core/fs/nilfs2.c
+++ b/grub-core/fs/nilfs2.c
@@ -753,7 +753,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data)
     partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size)
 		      >> GRUB_DISK_SECTOR_BITS);
   else
-    partition_size = grub_disk_get_size (disk);
+    partition_size = grub_disk_native_sectors (disk);
   if (partition_size != GRUB_DISK_SIZE_UNKNOWN)
     {
       /* Read second super block. */
diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
index 41ef0ff57..b6e1e178d 100644
--- a/grub-core/fs/zfs/zfs.c
+++ b/grub-core/fs/zfs/zfs.c
@@ -1175,7 +1175,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
   desc.original = original;
 
   /* Don't check back labels on CDROM.  */
-  if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
+  if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
     vdevnum = VDEV_LABELS / 2;
 
   for (label = 0; ubbest == NULL && label < vdevnum; label++)
@@ -1184,7 +1184,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
 	= label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
 	+ ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
 	+ (label < VDEV_LABELS / 2 ? 0 : 
-	   ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t))
+	   ALIGN_DOWN (grub_disk_native_sectors (dev->disk), sizeof (vdev_label_t))
 	   - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
 
       /* Read in the uberblock ring (128K). */
diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c
index ffb09c8ee..e1b0e073e 100644
--- a/grub-core/kern/disk.c
+++ b/grub-core/kern/disk.c
@@ -533,7 +533,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
 }
 
 grub_uint64_t
-grub_disk_get_size (grub_disk_t disk)
+grub_disk_native_sectors (grub_disk_t disk)
 {
   if (disk->partition)
     return grub_partition_get_len (disk->partition);
diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c
index 3834a1490..2ed3ff319 100644
--- a/grub-core/kern/mips/arc/init.c
+++ b/grub-core/kern/mips/arc/init.c
@@ -430,7 +430,7 @@ grub_machine_get_bootlocation (char **device, char **path)
     }
 
   if (poff == 0
-      && pend == grub_disk_get_size (parent))
+      && pend == grub_disk_native_sectors (parent))
     {
       grub_disk_close (parent);
       *device = dname;
diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c
index 435cd9234..8bb6da31f 100644
--- a/grub-core/normal/misc.c
+++ b/grub-core/normal/misc.c
@@ -176,14 +176,14 @@ grub_normal_print_device_info (const char *name)
 		     (grub_partition_get_start (dev->disk->partition) & 1) ? ".5" : "" );
       else
 	grub_printf_ (N_(" - Sector size %uB"), 1 << dev->disk->log_sector_size);
-      if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
+      if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
 	grub_puts_ (N_(" - Total size unknown"));
       else
 	grub_printf (_(" - Total size %llu%sKiB"),
-		     (unsigned long long) (grub_disk_get_size (dev->disk) >> 1),
+		     (unsigned long long) (grub_disk_native_sectors (dev->disk) >> 1),
 		     /* TRANSLATORS: Replace dot with appropriate decimal separator for
 			your language.  */
-		     (grub_disk_get_size (dev->disk) & 1) ? _(".5") : "");
+		     (grub_disk_native_sectors (dev->disk) & 1) ? _(".5") : "");
     }
 
   if (dev)
diff --git a/grub-core/osdep/windows/platform.c b/grub-core/osdep/windows/platform.c
index 1ef86bf58..253f8d101 100644
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -371,7 +371,7 @@ grub_install_register_efi (grub_device_t efidir_grub_dev,
 
   hddp->partition_start = grub_partition_get_start (efidir_grub_dev->disk->partition)
     >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
-  hddp->partition_size = grub_disk_get_size (efidir_grub_dev->disk)
+  hddp->partition_size = grub_disk_native_sectors (efidir_grub_dev->disk)
     >> (efidir_grub_dev->disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
 
   pathptr = hddp + 1;
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 132a1bb75..0fb727d3d 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -171,7 +171,7 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 
 #define GRUB_DISK_MAX_MAX_AGGLOMERATE ((1 << (30 - GRUB_DISK_CACHE_BITS - GRUB_DISK_SECTOR_BITS)) - 1)
 
-/* Return value of grub_disk_get_size() in case disk size is unknown. */
+/* Return value of grub_disk_native_sectors() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
 /* Convert to GRUB native disk sized sector from disk sized sector. */
@@ -219,7 +219,7 @@ extern grub_err_t (*EXPORT_VAR(grub_disk_write_weak)) (grub_disk_t disk,
 						       const void *buf);
 
 
-grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
+grub_uint64_t EXPORT_FUNC(grub_disk_native_sectors) (grub_disk_t disk);
 
 #if DISK_CACHE_STATS
 void
diff --git a/util/grub-install.c b/util/grub-install.c
index a35a2e2e8..f9f8ee7b2 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -748,7 +748,7 @@ is_prep_empty (grub_device_t dev)
   grub_disk_addr_t dsize, addr;
   grub_uint32_t buffer[32768];
 
-  dsize = grub_disk_get_size (dev->disk);
+  dsize = grub_disk_native_sectors (dev->disk);
   for (addr = 0; addr < dsize;
        addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
     {
diff --git a/util/grub-probe.c b/util/grub-probe.c
index cbe6ed94c..c08e46bbb 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -398,7 +398,7 @@ probe (const char *path, char **device_names, char delim)
 	  if (! dev || !dev->disk)
 	    grub_util_error ("%s", grub_errmsg);
 
-	  dsize = grub_disk_get_size (dev->disk);
+	  dsize = grub_disk_native_sectors (dev->disk);
 	  for (addr = 0; addr < dsize;
 	       addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
 	    {
-- 
2.27.0



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

* [PATCH v8 02/18] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 03/18] whitespace: convert 8 spaces to tabs Glenn Washburn
                             ` (16 subsequent siblings)
  18 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

This ensures that expected order of operations is preserved when arguments
are expressions.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 include/grub/misc.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index b7ca6dd58..780a34e90 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -28,10 +28,10 @@
 #include <grub/compiler.h>
 
 #define ALIGN_UP(addr, align) \
-	((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
+	(((addr) + (typeof (addr)) (align) - 1) & ~((typeof (addr)) (align) - 1))
 #define ALIGN_UP_OVERHEAD(addr, align) ((-(addr)) & ((typeof (addr)) (align) - 1))
 #define ALIGN_DOWN(addr, align) \
-	((addr) & ~((typeof (addr)) align - 1))
+	((addr) & ~((typeof (addr)) (align) - 1))
 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
 #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
 
-- 
2.27.0



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

* [PATCH v8 03/18] whitespace: convert 8 spaces to tabs
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 02/18] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 04/18] luks2: Remove unused argument in grub_error Glenn Washburn
                             ` (15 subsequent siblings)
  18 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index d96764a02..66e3b8798 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -276,8 +276,8 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
-          grub_json_getchild (&digest, &digest, 0) ||
-          luks2_parse_digest (d, &digest))
+	  grub_json_getchild (&digest, &digest, 0) ||
+	  luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
       if ((d->keyslots & (1 << idx)))
@@ -295,7 +295,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       if (grub_json_getchild (&segment, &segments, i) ||
 	  grub_json_getuint64 (&idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
-          luks2_parse_segment (s, &segment))
+	  luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
       if ((d->segments & (1 << idx)))
@@ -600,7 +600,7 @@ luks2_recover_key (grub_disk_t source,
 	{
 	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
 	  continue;
-        }
+	}
 
       grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
 
-- 
2.27.0



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

* [PATCH v8 04/18] luks2: Remove unused argument in grub_error
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (2 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 03/18] whitespace: convert 8 spaces to tabs Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 05/18] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
                             ` (14 subsequent siblings)
  18 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 66e3b8798..402926680 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -200,7 +200,7 @@ luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment)
       grub_json_getstring (&out->size, segment, "size") ||
       grub_json_getstring (&out->encryption, segment, "encryption") ||
       grub_json_getint64 (&out->sector_size, segment, "sector_size"))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters", type);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters");
 
   return GRUB_ERR_NONE;
 }
@@ -228,7 +228,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no segments", type);
+		       "Digest references no segments");
 
   for (i = 0; i < size; i++)
     {
@@ -240,7 +240,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
   if (grub_json_getsize (&size, &keyslots))
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
-		       "Digest references no keyslots", type);
+		       "Digest references no keyslots");
 
   for (i = 0; i < size; i++)
     {
-- 
2.27.0



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

* [PATCH v8 05/18] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (3 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 04/18] luks2: Remove unused argument in grub_error Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-08 22:45           ` [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
                             ` (13 subsequent siblings)
  18 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

We should assume that the output argument "out" is uninitialized and could
have random data. So, make sure to initialize the segments and keyslots bit
fields because potentially not all bits of those fields are written to.
Otherwise, the digest could say it belongs to keyslots and segments that it
does not.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/luks2.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 402926680..9b19d35c1 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -230,6 +230,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
 		       "Digest references no segments");
 
+  out->segments = 0;
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&o, &segments, i) ||
@@ -242,6 +243,7 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
     return grub_error (GRUB_ERR_BAD_ARGUMENT,
 		       "Digest references no keyslots");
 
+  out->keyslots = 0;
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&o, &keyslots, i) ||
-- 
2.27.0



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

* [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (4 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 05/18] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 18:02             ` Daniel Kiper
  2020-12-12  8:07             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages Glenn Washburn
                             ` (12 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows code using these structs to know the named key associated with
these json data structures. In the future we can use these to provide better
error messages to the user.

Get rid of idx local variable in luks2_get_keyslot() which was overloaded to
be used for both keyslot and segment slot keys.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 9b19d35c1..67b1823d3 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -65,6 +65,8 @@ typedef struct grub_luks2_header grub_luks2_header_t;
 
 struct grub_luks2_keyslot
 {
+  /* The integer key to the associative array of keyslots */
+  grub_uint64_t idx;
   grub_int64_t key_size;
   grub_int64_t priority;
   struct
@@ -103,6 +105,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
 
 struct grub_luks2_segment
 {
+  grub_uint64_t idx;
   grub_uint64_t offset;
   const char	*size;
   const char	*encryption;
@@ -112,6 +115,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
 
 struct grub_luks2_digest
 {
+  grub_uint64_t idx;
   /* Both keyslots and segments are interpreted as bitfields here */
   grub_uint64_t	keyslots;
   grub_uint64_t	segments;
@@ -261,12 +265,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
   grub_size_t i, size;
-  grub_uint64_t idx;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
       grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
-      grub_json_getuint64 (&idx, &keyslot, NULL) ||
+      grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
@@ -278,11 +281,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&digest, &digests, i) ||
+	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
 	  grub_json_getchild (&digest, &digest, 0) ||
 	  luks2_parse_digest (d, &digest))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
 
-      if ((d->keyslots & (1 << idx)))
+      if ((d->keyslots & (1 << k->idx)))
 	break;
     }
   if (i == size)
@@ -295,12 +299,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
   for (i = 0; i < size; i++)
     {
       if (grub_json_getchild (&segment, &segments, i) ||
-	  grub_json_getuint64 (&idx, &segment, NULL) ||
+	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
 	  luks2_parse_segment (s, &segment))
 	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
 
-      if ((d->segments & (1 << idx)))
+      if ((d->segments & (1 << s->idx)))
 	break;
     }
   if (i == size)
-- 
2.27.0



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

* [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (5 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 18:05             ` Daniel Kiper
  2020-12-12  8:09             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes Glenn Washburn
                             ` (11 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Use the object name in the json array rather than the 0 based index in the
json array for keyslots, segments, and digests. This is less confusing for
the end user. For example, say you have a LUKS2 device with a key in slot 1
and slot 4. When using the password for slot 4 to unlock the device, the
messages using the index of the keyslot will mention keyslot 1 (its a
zero-based index). Furthermore, with this change the keyslot number will
align with the number used to reference the keyslot when using the
--key-slot argument to cryptsetup.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 67b1823d3..b6930b2f5 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (i == size)
-      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->idx);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
@@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	break;
     }
   if (i == size)
-    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->idx);
 
   return GRUB_ERR_NONE;
 }
@@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
 
       if (keyslot.priority == 0)
 	{
-	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
+	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.idx);
 	  continue;
 	}
 
-      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
+      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
@@ -623,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
+			keyslot.idx, grub_errmsg);
 	  continue;
 	}
 
       ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
       if (ret)
 	{
-	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
-			i, grub_errmsg);
+	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
+			keyslot.idx, grub_errmsg);
 	  continue;
 	}
 
@@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
        * TRANSLATORS: It's a cryptographic key slot: one element of an array
        * where each element is either empty or holds a key.
        */
-      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
+      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.idx);
 
       candidate_key_len = keyslot.key_size;
       break;
-- 
2.27.0



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

* [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (6 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 18:07             ` Daniel Kiper
  2020-12-12  8:10             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index Glenn Washburn
                             ` (10 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index b6930b2f5..7e0419a82 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -261,53 +261,53 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
 
 static grub_err_t
 luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
-		   const grub_json_t *root, grub_size_t keyslot_idx)
+		   const grub_json_t *root, grub_size_t keyslot_json_idx)
 {
   grub_json_t keyslots, keyslot, digests, digest, segments, segment;
-  grub_size_t i, size;
+  grub_size_t json_idx, size;
 
   /* Get nth keyslot */
   if (grub_json_getvalue (&keyslots, root, "keyslots") ||
-      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
+      grub_json_getchild (&keyslot, &keyslots, keyslot_json_idx) ||
       grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_json_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
       grub_json_getsize (&size, &digests))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
-  for (i = 0; i < size; i++)
+  for (json_idx = 0; json_idx < size; json_idx++)
     {
-      if (grub_json_getchild (&digest, &digests, i) ||
+      if (grub_json_getchild (&digest, &digests, json_idx) ||
 	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
 	  grub_json_getchild (&digest, &digest, 0) ||
 	  luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, json_idx);
 
       if ((d->keyslots & (1 << k->idx)))
 	break;
     }
-  if (i == size)
+  if (json_idx == size)
       return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->idx);
 
   /* Get segment that matches the digest. */
   if (grub_json_getvalue (&segments, root, "segments") ||
       grub_json_getsize (&size, &segments))
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
-  for (i = 0; i < size; i++)
+  for (json_idx = 0; json_idx < size; json_idx++)
     {
-      if (grub_json_getchild (&segment, &segments, i) ||
+      if (grub_json_getchild (&segment, &segments, json_idx) ||
 	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
 	  luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, json_idx);
 
       if ((d->segments & (1 << s->idx)))
 	break;
     }
-  if (i == size)
+  if (json_idx == size)
     return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->idx);
 
   return GRUB_ERR_NONE;
@@ -542,7 +542,7 @@ luks2_recover_key (grub_disk_t source,
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
   char passphrase[MAX_PASSPHRASE], cipher[32];
   char *json_header = NULL, *part = NULL, *ptr;
-  grub_size_t candidate_key_len = 0, i, size;
+  grub_size_t candidate_key_len = 0, json_idx, size;
   grub_luks2_header_t header;
   grub_luks2_keyslot_t keyslot;
   grub_luks2_digest_t digest;
@@ -596,9 +596,9 @@ luks2_recover_key (grub_disk_t source,
     }
 
   /* Try all keyslot */
-  for (i = 0; i < size; i++)
+  for (json_idx = 0; json_idx < size; json_idx++)
     {
-      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
+      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
       if (ret)
 	goto err;
 
-- 
2.27.0



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

* [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index.
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (7 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 18:09             ` Daniel Kiper
  2020-12-12  8:11             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
                             ` (9 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This allows error messages to be more easily distinguishable between indexes
and slot keys. The former include the string "index" in the error/debug
string, and the later are surrounded in quotes.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 7e0419a82..ebf03e77b 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -272,7 +272,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
       grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
       grub_json_getchild (&keyslot, &keyslot, 0) ||
       luks2_parse_keyslot (k, &keyslot))
-    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_json_idx);
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_json_idx);
 
   /* Get digest that matches the keyslot. */
   if (grub_json_getvalue (&digests, root, "digests") ||
@@ -284,7 +284,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
 	  grub_json_getchild (&digest, &digest, 0) ||
 	  luks2_parse_digest (d, &digest))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, json_idx);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, json_idx);
 
       if ((d->keyslots & (1 << k->idx)))
 	break;
@@ -302,7 +302,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
 	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
 	  grub_json_getchild (&segment, &segment, 0) ||
 	  luks2_parse_segment (s, &segment))
-	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, json_idx);
+	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, json_idx);
 
       if ((d->segments & (1 << s->idx)))
 	break;
-- 
2.27.0



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

* [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (8 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-09 18:12             ` Daniel Kiper
  2020-12-12  8:12             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
                             ` (8 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 7 ++++---
 include/grub/types.h        | 2 ++
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 473c93976..0e955a020 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -281,20 +281,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> 32);
+	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
 	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
-	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
+	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
+					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
 				    & 0xFFFFFFFF);
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
-	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
+	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
 	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
 	  }
 	  break;
diff --git a/include/grub/types.h b/include/grub/types.h
index f22055f98..9989e3a16 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -80,6 +80,8 @@
 # define GRUB_CHAR_BIT	__CHAR_BIT__
 #endif
 
+#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
+
 /* Define various wide integers.  */
 typedef signed char		grub_int8_t;
 typedef short			grub_int16_t;
-- 
2.27.0



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

* [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (9 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-10 14:51             ` Daniel Kiper
  2020-12-12  8:13             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
                             ` (7 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
unsigned number with size of type.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/cryptodisk.c | 8 ++++----
 include/grub/types.h        | 7 +++++++
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 0e955a020..5aa0c4720 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
 	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
 					       - dev->log_sector_size));
 	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
-				    & 0xFFFFFFFF);
+				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
 	  {
 	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
 	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
-	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
+	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
-	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
+	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
 	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
 					 dev->cipher->cipher->blocksize);
 	  if (err)
diff --git a/include/grub/types.h b/include/grub/types.h
index 9989e3a16..b36b26a79 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
 #endif
 # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
 
+/*
+ * Cast to unsigned long long so that the "return value" is always a consistent
+ * type and to ensure an unsigned value regardless of type parameter.
+ */
+#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
+#define GRUB_TYPE_U_MIN(type) 0ULL
+
 typedef grub_uint64_t grub_properly_aligned_t;
 
 #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
-- 
2.27.0



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

* [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (10 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-12  8:14             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
                             ` (6 subsequent siblings)
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

We need to convert the sectors from the size of the underlying device to the
cryptodisk sector size; segment.size is in bytes which need to be converted
to cryptodisk sectors as well.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/luks2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index ebf03e77b..429a4cfa1 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
   grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
   grub_uint8_t *split_key = NULL;
   grub_size_t saltlen = sizeof (salt);
-  char cipher[32], *p;;
+  char cipher[32], *p;
   const gcry_md_spec_t *hash;
   gcry_err_code_t gcry_ret;
   grub_err_t ret;
@@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
+	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
+			       - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
-- 
2.27.0



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

* [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (11 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-12  8:15             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
                             ` (5 subsequent siblings)
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

By default, dm-crypt internally uses an IV that corresponds to 512-byte
sectors, even when a larger sector size is specified. What this means is
that when using a larger sector size, the IV is incremented every sector.
However, the amount the IV is incremented is the number of 512 byte blocks
in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
the number of, for example, 4K sectors. So each 512 byte cipher block in a
sector will be encrypted with the same IV and the IV will be incremented
afterwards by the number of 512 byte cipher blocks in the sector.

There are some encryption utilities which do it the intuitive way and have
the IV equal to the sector number regardless of sector size (ie. the fifth
sector would have an IV of 4 for each cipher block). And this is supported
by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
with the --iv-large-sectors, though not with LUKS headers (only with --type
plain). However, support for this has not been included as grub does not
support plain devices right now.

One gotcha here is that the encrypted split keys are encrypted with a hard-
coded 512-byte sector size. So even if your data is encrypted with 4K sector
sizes, the split key encrypted area must be decrypted with a block size of
512 (ie the IV increments every 512 bytes). This made these changes less
aestetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
 grub-core/disk/luks.c       |  5 ++--
 grub-core/disk/luks2.c      |  7 ++++-
 include/grub/cryptodisk.h   |  8 +++++-
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 5aa0c4720..b62835acc 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
 static gcry_err_code_t
 grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 			   grub_uint8_t * data, grub_size_t len,
-			   grub_disk_addr_t sector, int do_encrypt)
+			   grub_disk_addr_t sector, grub_size_t log_sector_size,
+			   int do_encrypt)
 {
   grub_size_t i;
   gcry_err_code_t err;
@@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
     return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
 	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
 
-  for (i = 0; i < len; i += (1U << dev->log_sector_size))
+  for (i = 0; i < len; i += (1U << log_sector_size))
     {
       grub_size_t sz = ((dev->cipher->cipher->blocksize
 			 + sizeof (grub_uint32_t) - 1)
@@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (!ctx)
 	      return GPG_ERR_OUT_OF_MEMORY;
 
-	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
+	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
 	    dev->iv_hash->init (ctx);
 	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
 	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
@@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
-	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
-	  /* FALLTHROUGH */
 	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
-	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
+	  /*
+	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
+	   * number. If using 32 bit IV mode, zero out the most significant
+	   * 32 bits.
+	   */
+	  {
+	    grub_uint64_t iv64;
+
+	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
+						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
+	    grub_set_unaligned64 (iv, iv64);
+	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
+	      iv[1] = 0;
+	  }
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
+	  /* The IV is the 64 bit byte offset of the sector. */
 	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
-					       - dev->log_sector_size));
-	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
+					       - log_sector_size));
+	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
 				    & GRUB_TYPE_U_MAX (iv[0]));
 	  break;
 	case GRUB_CRYPTODISK_MODE_IV_BENBI:
@@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_CBC:
 	  if (do_encrypt)
 	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size), iv);
+					   (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_PCBC:
 	  if (do_encrypt)
 	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  else
 	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
-					    (1U << dev->log_sector_size), iv);
+					    (1U << log_sector_size), iv);
 	  if (err)
 	    return err;
 	  break;
@@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (err)
 	      return err;
 	    
-	    for (j = 0; j < (1U << dev->log_sector_size);
+	    for (j = 0; j < (1U << log_sector_size);
 		 j += dev->cipher->cipher->blocksize)
 	      {
 		grub_crypto_xor (data + i + j, data + i + j, iv,
@@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	    if (do_encrypt)
 	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    else
 	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
 					     data + i,
-					     (1U << dev->log_sector_size));
+					     (1U << log_sector_size));
 	    if (err)
 	      return err;
 	    lrw_xor (&sec, dev, data + i);
@@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 	case GRUB_CRYPTODISK_MODE_ECB:
 	  if (do_encrypt)
 	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  else
 	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
-					   (1U << dev->log_sector_size));
+					   (1U << log_sector_size));
 	  if (err)
 	    return err;
 	  break;
@@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector)
+			 grub_disk_addr_t sector, grub_size_t log_sector_size)
 {
-  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
+  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
 }
 
 grub_err_t
@@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
     }
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
 					size << disk->log_sector_size,
-					sector, 0);
+					sector, dev->log_sector_size, 0);
   return grub_crypto_gcry_error (gcry_err);
 }
 
@@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
 
   gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
 					size << disk->log_sector_size,
-					sector, 1);
+					sector, disk->log_sector_size, 1);
   if (gcry_err)
     {
       grub_free (tmp);
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 5fc79d880..13103ea6a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
       return NULL;
   newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
   newdev->source_disk = NULL;
-  newdev->log_sector_size = 9;
+  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
   newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
   grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
   newdev->modname = "luks";
@@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
 	  return err;
 	}
 
-      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
+      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
+					  GRUB_LUKS1_LOG_SECTOR_SIZE);
       if (gcry_err)
 	{
 	  grub_free (split_key);
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 429a4cfa1..9abcb1c94 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
       goto err;
     }
 
-  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
+  /*
+   * The key slots area is always encrypted in 512-byte sectors,
+   * regardless of encrypted data sector size.
+   */
+  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
+				      GRUB_LUKS1_LOG_SECTOR_SIZE);
   if (gcry_ret)
     {
       ret = grub_crypto_gcry_error (gcry_ret);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index c9bf7597a..938912cf3 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -48,6 +48,12 @@ typedef enum
 
 #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
 
+/* LUKS1 specification defines the block size to always be 512 bytes. */
+#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
+
+/* By default dm-crypt increments the IV every 512 bytes. */
+#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
+
 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
 #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
@@ -144,7 +150,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
 gcry_err_code_t
 grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
 			 grub_uint8_t * data, grub_size_t len,
-			 grub_disk_addr_t sector);
+			 grub_disk_addr_t sector, grub_size_t log_sector_size);
 grub_err_t
 grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
 			grub_disk_t source);
-- 
2.27.0



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

* [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (12 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-10 16:07             ` Daniel Kiper
  2020-12-08 22:45           ` [PATCH v8 15/18] luks2: Error check segment.sector_size Glenn Washburn
                             ` (4 subsequent siblings)
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

First, check to make sure that source disk has a known size. If not, print
debug message and return error. There are 4 cases where
GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
all those cases processing continues. So this is probably a bit
conservative. However, 3 of the cases seem pathological, and the other,
biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
volume on a cd is a big use case, we'll error until someone complains.

Do some sanity checking on data coming from the luks header. If segment.size
is "dynamic", verify that the offset is not past the end of disk. Otherwise,
check for errors from grub_strtoull when converting segment size from
string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
returned, then there was an overflow in converting to a 64-bit unsigned
integer. So this could be a very large disk (perhaps large raid array).
In this case, we want to continue to try to use this key, but only allow
access up to the end of the source disk.

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 84 ++++++++++++++++++++++++++++++++++++++++--
 include/grub/disk.h    | 17 +++++++++
 2 files changed, 98 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 9abcb1c94..8cb11e899 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -600,12 +600,26 @@ luks2_recover_key (grub_disk_t source,
       goto err;
     }
 
+  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
+    {
+      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
+      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
+			     "conservatively returning error\n", source->name);
+      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
+      goto err;
+    }
+
   /* Try all keyslot */
   for (json_idx = 0; json_idx < size; json_idx++)
     {
+      typeof(source->total_sectors) max_crypt_sectors = 0;
+
+      grub_errno = GRUB_ERR_NONE;
       ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
       if (ret)
 	goto err;
+      if (grub_errno != GRUB_ERR_NONE)
+	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
 
       if (keyslot.priority == 0)
 	{
@@ -619,11 +633,75 @@ luks2_recover_key (grub_disk_t source,
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
 		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      /* Set to the source disk size, which is the maximum we allow. */
+      max_crypt_sectors = grub_disk_convert_sector(source,
+						   source->total_sectors,
+						   crypt->log_sector_size);
+
+      if (max_crypt_sectors < crypt->offset_sectors)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
+				 " %"PRIuGRUB_UINT64_T" which is greater than"
+				 " source disk size %"PRIuGRUB_UINT64_T","
+				 " skipping\n",
+				 segment.idx, crypt->offset_sectors,
+				 max_crypt_sectors);
+	  continue;
+	}
+
       if (grub_strcmp (segment.size, "dynamic") == 0)
-	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
-			       - crypt->offset_sectors;
+	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
       else
-	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
+	{
+	  grub_errno = GRUB_ERR_NONE;
+	  /* Convert segment.size to sectors, rounding up to nearest sector */
+	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
+	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
+					   1 << crypt->log_sector_size);
+	  crypt->total_sectors >>= crypt->log_sector_size;
+
+	  if (grub_errno == GRUB_ERR_NONE)
+	    ;
+	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
+	    {
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " \"%s\" is not a parsable number\n",
+				     segment.idx, segment.size);
+	      continue;
+	    }
+	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
+	    {
+	      /*
+	       * There was an overflow in parsing segment.size, so disk must
+	       * be very large or the string is incorrect.
+	       */
+	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
+				     " %s overflowed 64-bit unsigned integer,"
+				     " the end of the crypto device will be"
+				     " inaccessible\n",
+				     segment.idx, segment.size);
+	      if (crypt->total_sectors > max_crypt_sectors)
+		crypt->total_sectors = max_crypt_sectors;
+	    }
+	}
+
+      if (crypt->total_sectors == 0)
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
+				 " sectors, skipping\n",
+				 segment.idx);
+	  continue;
+	}
+      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
+				 " data position greater than source disk size,"
+				 " the end of the crypto device will be"
+				 " inaccessible\n",
+				 segment.idx);
+	  /* Allow decryption up to the end of the source disk. */
+	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
+	}
 
       ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
 			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 0fb727d3d..f9227f285 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -27,6 +27,8 @@
 #include <grub/device.h>
 /* For NULL.  */
 #include <grub/mm.h>
+/* For ALIGN_UP.  */
+#include <grub/misc.h>
 
 /* These are used to set a device id. When you add a new disk device,
    you must define a new id for it here.  */
@@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
 /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
 #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
 
+/* Convert sector number from disk sized sectors to a log-size sized sector. */
+static inline grub_disk_addr_t
+grub_disk_convert_sector (grub_disk_t disk,
+			  grub_disk_addr_t sector,
+			  grub_size_t log_sector_size)
+{
+  if (disk->log_sector_size < log_sector_size)
+    {
+      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));
+      return sector >> (log_sector_size - disk->log_sector_size);
+    }
+  else
+    return sector << (disk->log_sector_size - log_sector_size);
+}
+
 /* Convert to GRUB native disk sized sector from disk sized sector. */
 static inline grub_disk_addr_t
 grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
-- 
2.27.0



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

* [PATCH v8 15/18] luks2: Error check segment.sector_size
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (13 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-10 16:08             ` Daniel Kiper
  2020-12-12  8:16             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 16/18] mips: Enable __clzdi2() Glenn Washburn
                             ` (3 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

Signed-off-by: Glenn Washburn <development@efficientek.com>
---
 grub-core/disk/luks2.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 8cb11e899..c737797b9 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -629,6 +629,17 @@ luks2_recover_key (grub_disk_t source,
 
       grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
 
+      /* Sector size should be one of 512, 1024, 2048, or 4096. */
+      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
+	    segment.sector_size == 2048 || segment.sector_size == 4096))
+	{
+	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
+				 " size %"PRIuGRUB_UINT64_T" is not one of"
+				 " 512, 1024, 2048, or 4096\n",
+				 segment.idx, segment.sector_size);
+	  continue;
+	}
+
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
       crypt->log_sector_size = sizeof (unsigned int) * 8
-- 
2.27.0



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

* [PATCH v8 16/18] mips: Enable __clzdi2()
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (14 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 15/18] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-10 16:09             ` Daniel Kiper
  2020-12-12  8:16             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
                             ` (2 subsequent siblings)
  18 siblings, 2 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn

This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
__clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
enabled.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Suggested-by: Daniel Kiper <dkiper@net-space.pl>
---
 grub-core/kern/compiler-rt.c | 2 +-
 include/grub/compiler-rt.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
index a464200c6..2057c2e0c 100644
--- a/grub-core/kern/compiler-rt.c
+++ b/grub-core/kern/compiler-rt.c
@@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
 }
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 __clzdi2 (grub_uint64_t val)
 {
diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
index 7591980b4..17828b322 100644
--- a/include/grub/compiler-rt.h
+++ b/include/grub/compiler-rt.h
@@ -115,7 +115,7 @@ int
 EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
 #endif
 
-#if defined(__riscv) || defined(__sparc__)
+#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
 int
 EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
 #endif
-- 
2.27.0



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

* [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (15 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 16/18] mips: Enable __clzdi2() Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-12  8:17             ` Patrick Steinhardt
  2020-12-08 22:45           ` [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
  2020-12-10 16:20           ` [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux Daniel Kiper
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 include/grub/misc.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/grub/misc.h b/include/grub/misc.h
index 780a34e90..73a514eb1 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 
+#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
+                         - __builtin_clzll (n) - 1)
+
 #endif /* ! GRUB_MISC_HEADER */
-- 
2.27.0



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

* [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (16 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-12-08 22:45           ` Glenn Washburn
  2020-12-12  8:18             ` Patrick Steinhardt
  2020-12-10 16:20           ` [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux Daniel Kiper
  18 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-08 22:45 UTC (permalink / raw)
  To: grub-devel; +Cc: Patrick Steinhardt, Daniel Kiper, Glenn Washburn, Daniel Kiper

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 grub-core/disk/luks2.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index c737797b9..31b51f1d4 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -642,8 +642,7 @@ luks2_recover_key (grub_disk_t source,
 
       /* Set up disk according to keyslot's segment. */
       crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
-      crypt->log_sector_size = sizeof (unsigned int) * 8
-		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
+      crypt->log_sector_size = grub_log2ull (segment.sector_size);
       /* Set to the source disk size, which is the maximum we allow. */
       max_crypt_sectors = grub_disk_convert_sector(source,
 						   source->total_sectors,
-- 
2.27.0



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

* Re: [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors
  2020-12-08 22:45           ` [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
@ 2020-12-09 17:39             ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 17:39 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:32PM -0600, Glenn Washburn wrote:
> The function grub_disk_get_size is confusingly named because it actually
> returns a sector count where the sectors are sized in the grub native sector
> size. Rename to something more appropriate.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
> Reviewed-by: Patrick Steinhardt <ps@pks.im>

The proper order is:

Suggested-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

First I suggested the patch, you wrote it, Patrick reviewed the patch
and finally I did it.

I will fix it before committing.

Daniel


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

* Re: [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
  2020-12-08 22:45           ` [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
@ 2020-12-09 18:02             ` Daniel Kiper
  2020-12-12  8:07             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 18:02 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:37PM -0600, Glenn Washburn wrote:
> This allows code using these structs to know the named key associated with
> these json data structures. In the future we can use these to provide better
> error messages to the user.
>
> Get rid of idx local variable in luks2_get_keyslot() which was overloaded to
> be used for both keyslot and segment slot keys.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages
  2020-12-08 22:45           ` [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages Glenn Washburn
@ 2020-12-09 18:05             ` Daniel Kiper
  2020-12-12  8:09             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 18:05 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:38PM -0600, Glenn Washburn wrote:
> Use the object name in the json array rather than the 0 based index in the
> json array for keyslots, segments, and digests. This is less confusing for
> the end user. For example, say you have a LUKS2 device with a key in slot 1
> and slot 4. When using the password for slot 4 to unlock the device, the
> messages using the index of the keyslot will mention keyslot 1 (its a
> zero-based index). Furthermore, with this change the keyslot number will
> align with the number used to reference the keyslot when using the
> --key-slot argument to cryptsetup.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes
  2020-12-08 22:45           ` [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes Glenn Washburn
@ 2020-12-09 18:07             ` Daniel Kiper
  2020-12-12  8:10             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 18:07 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:39PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index.
  2020-12-08 22:45           ` [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index Glenn Washburn
@ 2020-12-09 18:09             ` Daniel Kiper
  2020-12-12  8:11             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 18:09 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:40PM -0600, Glenn Washburn wrote:
> This allows error messages to be more easily distinguishable between indexes
> and slot keys. The former include the string "index" in the error/debug
> string, and the later are surrounded in quotes.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-08 22:45           ` [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
@ 2020-12-09 18:12             ` Daniel Kiper
  2020-12-12  8:12             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-09 18:12 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:41PM -0600, Glenn Washburn wrote:
> The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
> type.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-08 22:45           ` [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
@ 2020-12-10 14:51             ` Daniel Kiper
  2020-12-12  8:13             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-10 14:51 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:42PM -0600, Glenn Washburn wrote:
> Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> unsigned number with size of type.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk
  2020-12-08 22:45           ` [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
@ 2020-12-10 16:07             ` Daniel Kiper
  2020-12-12  1:10               ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-10 16:07 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:45PM -0600, Glenn Washburn wrote:
> First, check to make sure that source disk has a known size. If not, print
> debug message and return error. There are 4 cases where
> GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and uboot), and in
> all those cases processing continues. So this is probably a bit
> conservative. However, 3 of the cases seem pathological, and the other,
> biosdisk, happens when booting from a cd. Since I doubt booting from a LUKS2
> volume on a cd is a big use case, we'll error until someone complains.
>
> Do some sanity checking on data coming from the luks header. If segment.size
> is "dynamic", verify that the offset is not past the end of disk. Otherwise,
> check for errors from grub_strtoull when converting segment size from
> string. If a GRUB_ERR_BAD_NUMBER error was returned, then the string was
> not a valid parsable number, so skip the key. If GRUB_ERR_OUT_OF_RANGE was
> returned, then there was an overflow in converting to a 64-bit unsigned
> integer. So this could be a very large disk (perhaps large raid array).
> In this case, we want to continue to try to use this key, but only allow
> access up to the end of the source disk.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
>  grub-core/disk/luks2.c | 84 ++++++++++++++++++++++++++++++++++++++++--
>  include/grub/disk.h    | 17 +++++++++
>  2 files changed, 98 insertions(+), 3 deletions(-)
>
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 9abcb1c94..8cb11e899 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -600,12 +600,26 @@ luks2_recover_key (grub_disk_t source,
>        goto err;
>      }
>
> +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> +    {
> +      /* FIXME: Allow use of source disk, and maybe cause errors in read. */
> +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> +			     "conservatively returning error\n", source->name);
> +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device");
> +      goto err;
> +    }
> +
>    /* Try all keyslot */
>    for (json_idx = 0; json_idx < size; json_idx++)
>      {
> +      typeof(source->total_sectors) max_crypt_sectors = 0;
> +
> +      grub_errno = GRUB_ERR_NONE;
>        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
>        if (ret)
>  	goto err;
> +      if (grub_errno != GRUB_ERR_NONE)
> +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno);
>
>        if (keyslot.priority == 0)
>  	{
> @@ -619,11 +633,75 @@ luks2_recover_key (grub_disk_t source,
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      /* Set to the source disk size, which is the maximum we allow. */
> +      max_crypt_sectors = grub_disk_convert_sector(source,
> +						   source->total_sectors,
> +						   crypt->log_sector_size);
> +
> +      if (max_crypt_sectors < crypt->offset_sectors)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has offset"
> +				 " %"PRIuGRUB_UINT64_T" which is greater than"
> +				 " source disk size %"PRIuGRUB_UINT64_T","
> +				 " skipping\n",
> +				 segment.idx, crypt->offset_sectors,
> +				 max_crypt_sectors);
> +	  continue;
> +	}
> +
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> -			       - crypt->offset_sectors;
> +	crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
> +	{
> +	  grub_errno = GRUB_ERR_NONE;
> +	  /* Convert segment.size to sectors, rounding up to nearest sector */
> +	  crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
> +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> +					   1 << crypt->log_sector_size);
> +	  crypt->total_sectors >>= crypt->log_sector_size;
> +
> +	  if (grub_errno == GRUB_ERR_NONE)
> +	    ;
> +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> +	    {
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " \"%s\" is not a parsable number\n",
> +				     segment.idx, segment.size);
> +	      continue;
> +	    }
> +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> +	    {
> +	      /*
> +	       * There was an overflow in parsing segment.size, so disk must
> +	       * be very large or the string is incorrect.
> +	       */
> +	      grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" size"
> +				     " %s overflowed 64-bit unsigned integer,"
> +				     " the end of the crypto device will be"
> +				     " inaccessible\n",
> +				     segment.idx, segment.size);
> +	      if (crypt->total_sectors > max_crypt_sectors)

I think this if is bogus. You should clamp crypt->total_sectors
without any checks here.

> +		crypt->total_sectors = max_crypt_sectors;
> +	    }
> +	}
> +
> +      if (crypt->total_sectors == 0)
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has zero"
> +				 " sectors, skipping\n",
> +				 segment.idx);
> +	  continue;
> +	}
> +      else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" has last"
> +				 " data position greater than source disk size,"
> +				 " the end of the crypto device will be"
> +				 " inaccessible\n",
> +				 segment.idx);
> +	  /* Allow decryption up to the end of the source disk. */
> +	  crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors;
> +	}
>
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> diff --git a/include/grub/disk.h b/include/grub/disk.h
> index 0fb727d3d..f9227f285 100644
> --- a/include/grub/disk.h
> +++ b/include/grub/disk.h
> @@ -27,6 +27,8 @@
>  #include <grub/device.h>
>  /* For NULL.  */
>  #include <grub/mm.h>
> +/* For ALIGN_UP.  */
> +#include <grub/misc.h>
>
>  /* These are used to set a device id. When you add a new disk device,
>     you must define a new id for it here.  */
> @@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
>  /* Return value of grub_disk_native_sectors() in case disk size is unknown. */
>  #define GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
>
> +/* Convert sector number from disk sized sectors to a log-size sized sector. */
> +static inline grub_disk_addr_t
> +grub_disk_convert_sector (grub_disk_t disk,
> +			  grub_disk_addr_t sector,
> +			  grub_size_t log_sector_size)
> +{
> +  if (disk->log_sector_size < log_sector_size)
> +    {
> +      sector = ALIGN_UP (sector, 1 << (log_sector_size / disk->log_sector_size));

s#/#-#?

> +      return sector >> (log_sector_size - disk->log_sector_size);
> +    }
> +  else
> +    return sector << (disk->log_sector_size - log_sector_size);
> +}

Daniel


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

* Re: [PATCH v8 15/18] luks2: Error check segment.sector_size
  2020-12-08 22:45           ` [PATCH v8 15/18] luks2: Error check segment.sector_size Glenn Washburn
@ 2020-12-10 16:08             ` Daniel Kiper
  2020-12-12  8:16             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-10 16:08 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:46PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 16/18] mips: Enable __clzdi2()
  2020-12-08 22:45           ` [PATCH v8 16/18] mips: Enable __clzdi2() Glenn Washburn
@ 2020-12-10 16:09             ` Daniel Kiper
  2020-12-12  8:16             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-10 16:09 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:47PM -0600, Glenn Washburn wrote:
> This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
> __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
> enabled.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Suggested-by: Daniel Kiper <dkiper@net-space.pl>

Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Daniel


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

* Re: [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
                             ` (17 preceding siblings ...)
  2020-12-08 22:45           ` [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
@ 2020-12-10 16:20           ` Daniel Kiper
  2020-12-12  8:20             ` Patrick Steinhardt
  18 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-10 16:20 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Tue, Dec 08, 2020 at 04:45:31PM -0600, Glenn Washburn wrote:
> This patch series, fixes issues with v7 series. Some of those patches had
> changes applied to the wrong patch. The added structure member was renamed
> again, this time to idx. And there is an added patch that renames some json
> index variables to note that they are such.
>
> Glenn
>
> Glenn Washburn (18):
>   disk: Rename grub_disk_get_size to grub_disk_native_sectors
>   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
>   whitespace: convert 8 spaces to tabs
>   luks2: Remove unused argument in grub_error
>   luks2: Make sure all fields of output argument in luks2_parse_digest()
>     are written to
>   luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
>   luks2: Use more intuitive object name instead of json index in user
>     messages
>   luks2: Rename json index variables to names that they are obviously
>     json indexes
>   luks2: Add string "index" to user strings using a json index.
>   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
>   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
>   luks2: grub_cryptodisk_t->total_sectors is the max number of device
>     native sectors
>   cryptodisk: Properly handle non-512 byte sized sectors
>   luks2: Better error handling when setting up the cryptodisk
>   luks2: Error check segment.sector_size
>   mips: Enable __clzdi2()
>   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
>     integers
>   luks2: Use grub_log2ull to calculate log_sector_size and improve
>     readability

I will get all the patches except #14 and maybe some changes after that
one which does not apply due to lack of it.

Thank you for doing the work!

Daniel


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

* Re: [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk
  2020-12-10 16:07             ` Daniel Kiper
@ 2020-12-12  1:10               ` Glenn Washburn
  2020-12-12 15:19                 ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Glenn Washburn @ 2020-12-12  1:10 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Thu, 10 Dec 2020 17:07:07 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Tue, Dec 08, 2020 at 04:45:45PM -0600, Glenn Washburn wrote:
> > First, check to make sure that source disk has a known size. If
> > not, print debug message and return error. There are 4 cases where
> > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > uboot), and in all those cases processing continues. So this is
> > probably a bit conservative. However, 3 of the cases seem
> > pathological, and the other, biosdisk, happens when booting from a
> > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > case, we'll error until someone complains.
> >
> > Do some sanity checking on data coming from the luks header. If
> > segment.size is "dynamic", verify that the offset is not past the
> > end of disk. Otherwise, check for errors from grub_strtoull when
> > converting segment size from string. If a GRUB_ERR_BAD_NUMBER error
> > was returned, then the string was not a valid parsable number, so
> > skip the key. If GRUB_ERR_OUT_OF_RANGE was returned, then there was
> > an overflow in converting to a 64-bit unsigned integer. So this
> > could be a very large disk (perhaps large raid array). In this
> > case, we want to continue to try to use this key, but only allow
> > access up to the end of the source disk.
> >
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  grub-core/disk/luks2.c | 84
> > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h    |
> > 17 +++++++++ 2 files changed, 98 insertions(+), 3 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index 9abcb1c94..8cb11e899 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -600,12 +600,26 @@ luks2_recover_key (grub_disk_t source,
> >        goto err;
> >      }
> >
> > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > +    {
> > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > in read. */
> > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > +			     "conservatively returning error\n",
> > source->name);
> > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > source device");
> > +      goto err;
> > +    }
> > +
> >    /* Try all keyslot */
> >    for (json_idx = 0; json_idx < size; json_idx++)
> >      {
> > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > +
> > +      grub_errno = GRUB_ERR_NONE;
> >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > json_idx); if (ret)
> >  	goto err;
> > +      if (grub_errno != GRUB_ERR_NONE)
> > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> > luks2_get_keyslot\n", grub_errno);
> >
> >        if (keyslot.priority == 0)
> >  	{
> > @@ -619,11 +633,75 @@ luks2_recover_key (grub_disk_t source,
> >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > (unsigned int) * 8
> >  		- __builtin_clz ((unsigned int)
> > segment.sector_size) - 1;
> > +      /* Set to the source disk size, which is the maximum we
> > allow. */
> > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > +
> > source->total_sectors,
> > +
> > crypt->log_sector_size); +
> > +      if (max_crypt_sectors < crypt->offset_sectors)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has offset"
> > +				 " %"PRIuGRUB_UINT64_T" which is
> > greater than"
> > +				 " source disk size
> > %"PRIuGRUB_UINT64_T","
> > +				 " skipping\n",
> > +				 segment.idx,
> > crypt->offset_sectors,
> > +				 max_crypt_sectors);
> > +	  continue;
> > +	}
> > +
> >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > (crypt->log_sector_size - source->log_sector_size))
> > -			       - crypt->offset_sectors;
> > +	crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors; else
> > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > 10) >> crypt->log_sector_size;
> > +	{
> > +	  grub_errno = GRUB_ERR_NONE;
> > +	  /* Convert segment.size to sectors, rounding up to
> > nearest sector */
> > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > NULL, 10);
> > +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> > +					   1 <<
> > crypt->log_sector_size);
> > +	  crypt->total_sectors >>= crypt->log_sector_size;
> > +
> > +	  if (grub_errno == GRUB_ERR_NONE)
> > +	    ;
> > +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> > +	    {
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " \"%s\" is not a parsable
> > number\n",
> > +				     segment.idx, segment.size);
> > +	      continue;
> > +	    }
> > +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > +	    {
> > +	      /*
> > +	       * There was an overflow in parsing segment.size, so
> > disk must
> > +	       * be very large or the string is incorrect.
> > +	       */
> > +	      grub_dprintf ("luks2", "Segment
> > \"%"PRIuGRUB_UINT64_T"\" size"
> > +				     " %s overflowed 64-bit
> > unsigned integer,"
> > +				     " the end of the crypto
> > device will be"
> > +				     " inaccessible\n",
> > +				     segment.idx, segment.size);
> > +	      if (crypt->total_sectors > max_crypt_sectors)
> 
> I think this if is bogus. You should clamp crypt->total_sectors
> without any checks here.

Actually, I wouldn't call this a clamp because in the overflow case
crypt->total_sectors always equals 0.  I just realized this, and its
because grub_strtoull will return 2^64-1 thus causing the following
ALIGN_UP to overflow returning 0.  Suffice to say that's not what we
want. My original intent was what happened before the ALIGN_UP code was
introduced, which would ALIGN_DOWN.

Here's an example illustrating why I wanted and still think the intent
of this check is reasonable. Suppose we have a disk size 2^67 bytes
with 512 byte (2^9) sized sectors. It will have 2^58 sectors. Further
suppose, there is a LUKS volume with size 2^65 bytes starting at the
beginning and a sector size of 4096 bytes (2^12). This will cause an
overflow, so grub_strtoull will return 2^64-1, this should have us set
crypt->total_sectors to 2^52-1. Since we don't know how much the
overflow is (1 byte or 1 terabyte), we don't know how many more sectors
til the end of the LUKS encrypted area. In this case max_crypt_sectors
will be 2^(58+9-12) => 2^57 sectors.  So here we see that
crypt->total_sectors < max_crypt_sectors in the overflow case.  If we
do as you suggest crypt->total_sectors will be set to 2^57, and thus
it will be valid to read past the end of the encrypted data (ie. block
2^56 of the 4k sector crypt will be a sector starting at byte 2^68,
which is more than the 2^65 byte size volume).

On the one hand, I like your suggestion because it allows reading all
possible encrypted data, at the cost of reading, decrypting, and
returning non-encrypted data (ie random garbage).  While keeping the
check, will prevent returning garbage at the cost of not allowing
access to all encrypted sectors. I think we should keep the check and
document a known limitation of 2^64 byte maximum sized LUKS volumes.
And that larger sized volumes can be read only up to byte 2^64. 

> > +		crypt->total_sectors = max_crypt_sectors;
> > +	    }
> > +	}
> > +
> > +      if (crypt->total_sectors == 0)
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has zero"
> > +				 " sectors, skipping\n",
> > +				 segment.idx);
> > +	  continue;
> > +	}
> > +      else if (max_crypt_sectors < (crypt->offset_sectors +
> > crypt->total_sectors))
> > +	{
> > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > has last"
> > +				 " data position greater than
> > source disk size,"
> > +				 " the end of the crypto device
> > will be"
> > +				 " inaccessible\n",
> > +				 segment.idx);
> > +	  /* Allow decryption up to the end of the source disk. */
> > +	  crypt->total_sectors = max_crypt_sectors -
> > crypt->offset_sectors;
> > +	}
> >
> >        ret = luks2_decrypt_key (candidate_key, source, crypt,
> > &keyslot, (const grub_uint8_t *) passphrase, grub_strlen
> > (passphrase)); diff --git a/include/grub/disk.h
> > b/include/grub/disk.h index 0fb727d3d..f9227f285 100644
> > --- a/include/grub/disk.h
> > +++ b/include/grub/disk.h
> > @@ -27,6 +27,8 @@
> >  #include <grub/device.h>
> >  /* For NULL.  */
> >  #include <grub/mm.h>
> > +/* For ALIGN_UP.  */
> > +#include <grub/misc.h>
> >
> >  /* These are used to set a device id. When you add a new disk
> > device, you must define a new id for it here.  */
> > @@ -174,6 +176,21 @@ typedef struct grub_disk_memberlist
> > *grub_disk_memberlist_t; /* Return value of
> > grub_disk_native_sectors() in case disk size is unknown. */ #define
> > GRUB_DISK_SIZE_UNKNOWN	 0xffffffffffffffffULL
> >
> > +/* Convert sector number from disk sized sectors to a log-size
> > sized sector. */ +static inline grub_disk_addr_t
> > +grub_disk_convert_sector (grub_disk_t disk,
> > +			  grub_disk_addr_t sector,
> > +			  grub_size_t log_sector_size)
> > +{
> > +  if (disk->log_sector_size < log_sector_size)
> > +    {
> > +      sector = ALIGN_UP (sector, 1 << (log_sector_size /
> > disk->log_sector_size));
> 
> s#/#-#?

Yep, looks like this passed my tests because an overflow is caused and
crypt->total_sectors is set to a very large value, which doesn't affect
the tests. I'll fix it.

Glenn

> > +      return sector >> (log_sector_size - disk->log_sector_size);
> > +    }
> > +  else
> > +    return sector << (disk->log_sector_size - log_sector_size);
> > +}
> 
> Daniel


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

* Re: [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
  2020-12-08 22:45           ` [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
  2020-12-09 18:02             ` Daniel Kiper
@ 2020-12-12  8:07             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:07 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:37PM -0600, Glenn Washburn wrote:
> This allows code using these structs to know the named key associated with
> these json data structures. In the future we can use these to provide better
> error messages to the user.
> 
> Get rid of idx local variable in luks2_get_keyslot() which was overloaded to
> be used for both keyslot and segment slot keys.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 9b19d35c1..67b1823d3 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -65,6 +65,8 @@ typedef struct grub_luks2_header grub_luks2_header_t;
>  
>  struct grub_luks2_keyslot
>  {
> +  /* The integer key to the associative array of keyslots */
> +  grub_uint64_t idx;
>    grub_int64_t key_size;
>    grub_int64_t priority;
>    struct
> @@ -103,6 +105,7 @@ typedef struct grub_luks2_keyslot grub_luks2_keyslot_t;
>  
>  struct grub_luks2_segment
>  {
> +  grub_uint64_t idx;
>    grub_uint64_t offset;
>    const char	*size;
>    const char	*encryption;
> @@ -112,6 +115,7 @@ typedef struct grub_luks2_segment grub_luks2_segment_t;
>  
>  struct grub_luks2_digest
>  {
> +  grub_uint64_t idx;
>    /* Both keyslots and segments are interpreted as bitfields here */
>    grub_uint64_t	keyslots;
>    grub_uint64_t	segments;
> @@ -261,12 +265,11 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
>    grub_size_t i, size;
> -  grub_uint64_t idx;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
>        grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> -      grub_json_getuint64 (&idx, &keyslot, NULL) ||
> +      grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> @@ -278,11 +281,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&digest, &digests, i) ||
> +	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
>  	  grub_json_getchild (&digest, &digest, 0) ||
>  	  luks2_parse_digest (d, &digest))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->keyslots & (1 << idx)))
> +      if ((d->keyslots & (1 << k->idx)))
>  	break;
>      }
>    if (i == size)
> @@ -295,12 +299,12 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>    for (i = 0; i < size; i++)
>      {
>        if (grub_json_getchild (&segment, &segments, i) ||
> -	  grub_json_getuint64 (&idx, &segment, NULL) ||
> +	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>  	  luks2_parse_segment (s, &segment))
>  	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
>  
> -      if ((d->segments & (1 << idx)))
> +      if ((d->segments & (1 << s->idx)))
>  	break;
>      }
>    if (i == size)
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages
  2020-12-08 22:45           ` [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages Glenn Washburn
  2020-12-09 18:05             ` Daniel Kiper
@ 2020-12-12  8:09             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:09 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:38PM -0600, Glenn Washburn wrote:
> Use the object name in the json array rather than the 0 based index in the
> json array for keyslots, segments, and digests. This is less confusing for
> the end user. For example, say you have a LUKS2 device with a key in slot 1
> and slot 4. When using the password for slot 4 to unlock the device, the
> messages using the index of the keyslot will mention keyslot 1 (its a
> zero-based index). Furthermore, with this change the keyslot number will
> align with the number used to reference the keyslot when using the
> --key-slot argument to cryptsetup.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 67b1823d3..b6930b2f5 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -290,7 +290,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->idx);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
> @@ -308,7 +308,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	break;
>      }
>    if (i == size)
> -    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE);
> +    return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->idx);
>  
>    return GRUB_ERR_NONE;
>  }
> @@ -604,11 +604,11 @@ luks2_recover_key (grub_disk_t source,
>  
>        if (keyslot.priority == 0)
>  	{
> -	  grub_dprintf ("luks2", "Ignoring keyslot %"PRIuGRUB_SIZE" due to priority\n", i);
> +	  grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T"\" due to priority\n", keyslot.idx);
>  	  continue;
>  	}
>  
> -      grub_dprintf ("luks2", "Trying keyslot %"PRIuGRUB_SIZE"\n", i);
> +      grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> @@ -623,16 +623,16 @@ luks2_recover_key (grub_disk_t source,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Decryption with keyslot %"PRIuGRUB_SIZE" failed: %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T"\" failed: %s\n",
> +			keyslot.idx, grub_errmsg);
>  	  continue;
>  	}
>  
>        ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size);
>        if (ret)
>  	{
> -	  grub_dprintf ("luks2", "Could not open keyslot %"PRIuGRUB_SIZE": %s\n",
> -			i, grub_errmsg);
> +	  grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T"\": %s\n",
> +			keyslot.idx, grub_errmsg);
>  	  continue;
>  	}
>  
> @@ -640,7 +640,7 @@ luks2_recover_key (grub_disk_t source,
>         * TRANSLATORS: It's a cryptographic key slot: one element of an array
>         * where each element is either empty or holds a key.
>         */
> -      grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> +      grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T"\" opened\n"), keyslot.idx);
>  
>        candidate_key_len = keyslot.key_size;
>        break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes
  2020-12-08 22:45           ` [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes Glenn Washburn
  2020-12-09 18:07             ` Daniel Kiper
@ 2020-12-12  8:10             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:10 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:39PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 30 +++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index b6930b2f5..7e0419a82 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -261,53 +261,53 @@ luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest)
>  
>  static grub_err_t
>  luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s,
> -		   const grub_json_t *root, grub_size_t keyslot_idx)
> +		   const grub_json_t *root, grub_size_t keyslot_json_idx)
>  {
>    grub_json_t keyslots, keyslot, digests, digest, segments, segment;
> -  grub_size_t i, size;
> +  grub_size_t json_idx, size;
>  
>    /* Get nth keyslot */
>    if (grub_json_getvalue (&keyslots, root, "keyslots") ||
> -      grub_json_getchild (&keyslot, &keyslots, keyslot_idx) ||
> +      grub_json_getchild (&keyslot, &keyslots, keyslot_json_idx) ||
>        grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_idx);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_json_idx);
>  
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
>        grub_json_getsize (&size, &digests))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests");
> -  for (i = 0; i < size; i++)
> +  for (json_idx = 0; json_idx < size; json_idx++)
>      {
> -      if (grub_json_getchild (&digest, &digests, i) ||
> +      if (grub_json_getchild (&digest, &digests, json_idx) ||
>  	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
>  	  grub_json_getchild (&digest, &digest, 0) ||
>  	  luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, json_idx);
>  
>        if ((d->keyslots & (1 << k->idx)))
>  	break;
>      }
> -  if (i == size)
> +  if (json_idx == size)
>        return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%"PRIuGRUB_UINT64_T"\"", k->idx);
>  
>    /* Get segment that matches the digest. */
>    if (grub_json_getvalue (&segments, root, "segments") ||
>        grub_json_getsize (&size, &segments))
>      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments");
> -  for (i = 0; i < size; i++)
> +  for (json_idx = 0; json_idx < size; json_idx++)
>      {
> -      if (grub_json_getchild (&segment, &segments, i) ||
> +      if (grub_json_getchild (&segment, &segments, json_idx) ||
>  	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>  	  luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, i);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, json_idx);
>  
>        if ((d->segments & (1 << s->idx)))
>  	break;
>      }
> -  if (i == size)
> +  if (json_idx == size)
>      return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"PRIuGRUB_UINT64_T"\"", d->idx);
>  
>    return GRUB_ERR_NONE;
> @@ -542,7 +542,7 @@ luks2_recover_key (grub_disk_t source,
>    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
>    char passphrase[MAX_PASSPHRASE], cipher[32];
>    char *json_header = NULL, *part = NULL, *ptr;
> -  grub_size_t candidate_key_len = 0, i, size;
> +  grub_size_t candidate_key_len = 0, json_idx, size;
>    grub_luks2_header_t header;
>    grub_luks2_keyslot_t keyslot;
>    grub_luks2_digest_t digest;
> @@ -596,9 +596,9 @@ luks2_recover_key (grub_disk_t source,
>      }
>  
>    /* Try all keyslot */
> -  for (i = 0; i < size; i++)
> +  for (json_idx = 0; json_idx < size; json_idx++)
>      {
> -      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i);
> +      ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
>        if (ret)
>  	goto err;
>  
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index.
  2020-12-08 22:45           ` [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index Glenn Washburn
  2020-12-09 18:09             ` Daniel Kiper
@ 2020-12-12  8:11             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:11 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:40PM -0600, Glenn Washburn wrote:
> This allows error messages to be more easily distinguishable between indexes
> and slot keys. The former include the string "index" in the error/debug
> string, and the later are surrounded in quotes.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Nit: the commit subject still has a trailing dot. I guess Daniel can fix
it when applying, though. So:

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 7e0419a82..ebf03e77b 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -272,7 +272,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>        grub_json_getuint64 (&k->idx, &keyslot, NULL) ||
>        grub_json_getchild (&keyslot, &keyslot, 0) ||
>        luks2_parse_keyslot (k, &keyslot))
> -    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot %"PRIuGRUB_SIZE, keyslot_json_idx);
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %"PRIuGRUB_SIZE, keyslot_json_idx);
>  
>    /* Get digest that matches the keyslot. */
>    if (grub_json_getvalue (&digests, root, "digests") ||
> @@ -284,7 +284,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&d->idx, &digest, NULL) ||
>  	  grub_json_getchild (&digest, &digest, 0) ||
>  	  luks2_parse_digest (d, &digest))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest %"PRIuGRUB_SIZE, json_idx);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %"PRIuGRUB_SIZE, json_idx);
>  
>        if ((d->keyslots & (1 << k->idx)))
>  	break;
> @@ -302,7 +302,7 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_s
>  	  grub_json_getuint64 (&s->idx, &segment, NULL) ||
>  	  grub_json_getchild (&segment, &segment, 0) ||
>  	  luks2_parse_segment (s, &segment))
> -	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment %"PRIuGRUB_SIZE, json_idx);
> +	return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %"PRIuGRUB_SIZE, json_idx);
>  
>        if ((d->segments & (1 << s->idx)))
>  	break;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
  2020-12-08 22:45           ` [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
  2020-12-09 18:12             ` Daniel Kiper
@ 2020-12-12  8:12             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:12 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:41PM -0600, Glenn Washburn wrote:
> The new macro GRUB_TYPE_BITS(type) returns the number of bits allocated for
> type.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 7 ++++---
>  include/grub/types.h        | 2 ++
>  2 files changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 473c93976..0e955a020 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -281,20 +281,21 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> 32);
> +	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
>  	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
> +	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> +					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
>  				    & 0xFFFFFFFF);
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
> -	    iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
> +	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
>  	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
>  	  }
>  	  break;
> diff --git a/include/grub/types.h b/include/grub/types.h
> index f22055f98..9989e3a16 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -80,6 +80,8 @@
>  # define GRUB_CHAR_BIT	__CHAR_BIT__
>  #endif
>  
> +#define GRUB_TYPE_BITS(type) (sizeof(type) * GRUB_CHAR_BIT)
> +
>  /* Define various wide integers.  */
>  typedef signed char		grub_int8_t;
>  typedef short			grub_int16_t;
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
  2020-12-08 22:45           ` [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
  2020-12-10 14:51             ` Daniel Kiper
@ 2020-12-12  8:13             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:13 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:42PM -0600, Glenn Washburn wrote:
> Add GRUB_TYPE_U_MAX/MIN(type) macros to get the max/min values for an
> unsigned number with size of type.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 8 ++++----
>  include/grub/types.h        | 7 +++++++
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 0e955a020..5aa0c4720 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -284,23 +284,23 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
>  	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
>  					       - dev->log_sector_size));
>  	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> -				    & 0xFFFFFFFF);
> +				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
>  	  {
>  	    grub_uint64_t num = (sector << dev->benbi_log) + 1;
>  	    iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0]));
> -	    iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
> +	    iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0]));
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_ESSIV:
> -	  iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
> +	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
>  	  err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
>  					 dev->cipher->cipher->blocksize);
>  	  if (err)
> diff --git a/include/grub/types.h b/include/grub/types.h
> index 9989e3a16..b36b26a79 100644
> --- a/include/grub/types.h
> +++ b/include/grub/types.h
> @@ -161,6 +161,13 @@ typedef grub_int32_t	grub_ssize_t;
>  #endif
>  # define GRUB_LONG_MIN (-GRUB_LONG_MAX - 1)
>  
> +/*
> + * Cast to unsigned long long so that the "return value" is always a consistent
> + * type and to ensure an unsigned value regardless of type parameter.
> + */
> +#define GRUB_TYPE_U_MAX(type) ((unsigned long long)((typeof (type))(~0)))
> +#define GRUB_TYPE_U_MIN(type) 0ULL
> +
>  typedef grub_uint64_t grub_properly_aligned_t;
>  
>  #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)]
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors
  2020-12-08 22:45           ` [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
@ 2020-12-12  8:14             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:14 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:43PM -0600, Glenn Washburn wrote:
> We need to convert the sectors from the size of the underlying device to the
> cryptodisk sector size; segment.size is in bytes which need to be converted
> to cryptodisk sectors as well.
> 
> Also, removed an empty statement.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index ebf03e77b..429a4cfa1 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -429,7 +429,7 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>    grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN];
>    grub_uint8_t *split_key = NULL;
>    grub_size_t saltlen = sizeof (salt);
> -  char cipher[32], *p;;
> +  char cipher[32], *p;
>    const gcry_md_spec_t *hash;
>    gcry_err_code_t gcry_ret;
>    grub_err_t ret;
> @@ -615,9 +615,10 @@ luks2_recover_key (grub_disk_t source,
>        crypt->log_sector_size = sizeof (unsigned int) * 8
>  		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
>        if (grub_strcmp (segment.size, "dynamic") == 0)
> -	crypt->total_sectors = grub_disk_get_size (source) - crypt->offset_sectors;
> +	crypt->total_sectors = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->log_sector_size))
> +			       - crypt->offset_sectors;
>        else
> -	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10);
> +	crypt->total_sectors = grub_strtoull (segment.size, NULL, 10) >> crypt->log_sector_size;
>  
>        ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
>  			       (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors
  2020-12-08 22:45           ` [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
@ 2020-12-12  8:15             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:15 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:44PM -0600, Glenn Washburn wrote:
> By default, dm-crypt internally uses an IV that corresponds to 512-byte
> sectors, even when a larger sector size is specified. What this means is
> that when using a larger sector size, the IV is incremented every sector.
> However, the amount the IV is incremented is the number of 512 byte blocks
> in a sector (ie 8 for 4K sectors). Confusingly the IV does not corespond to
> the number of, for example, 4K sectors. So each 512 byte cipher block in a
> sector will be encrypted with the same IV and the IV will be incremented
> afterwards by the number of 512 byte cipher blocks in the sector.
> 
> There are some encryption utilities which do it the intuitive way and have
> the IV equal to the sector number regardless of sector size (ie. the fifth
> sector would have an IV of 4 for each cipher block). And this is supported
> by dm-crypt with the iv_large_sectors option and also cryptsetup as of 2.3.3
> with the --iv-large-sectors, though not with LUKS headers (only with --type
> plain). However, support for this has not been included as grub does not
> support plain devices right now.
> 
> One gotcha here is that the encrypted split keys are encrypted with a hard-
> coded 512-byte sector size. So even if your data is encrypted with 4K sector
> sizes, the split key encrypted area must be decrypted with a block size of
> 512 (ie the IV increments every 512 bytes). This made these changes less
> aestetically pleasing than desired.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/cryptodisk.c | 55 +++++++++++++++++++++++--------------
>  grub-core/disk/luks.c       |  5 ++--
>  grub-core/disk/luks2.c      |  7 ++++-
>  include/grub/cryptodisk.h   |  8 +++++-
>  4 files changed, 50 insertions(+), 25 deletions(-)
> 
> diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
> index 5aa0c4720..b62835acc 100644
> --- a/grub-core/disk/cryptodisk.c
> +++ b/grub-core/disk/cryptodisk.c
> @@ -224,7 +224,8 @@ lrw_xor (const struct lrw_sector *sec,
>  static gcry_err_code_t
>  grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  			   grub_uint8_t * data, grub_size_t len,
> -			   grub_disk_addr_t sector, int do_encrypt)
> +			   grub_disk_addr_t sector, grub_size_t log_sector_size,
> +			   int do_encrypt)
>  {
>    grub_size_t i;
>    gcry_err_code_t err;
> @@ -237,7 +238,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>      return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
>  	    : grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
>  
> -  for (i = 0; i < len; i += (1U << dev->log_sector_size))
> +  for (i = 0; i < len; i += (1U << log_sector_size))
>      {
>        grub_size_t sz = ((dev->cipher->cipher->blocksize
>  			 + sizeof (grub_uint32_t) - 1)
> @@ -270,7 +271,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (!ctx)
>  	      return GPG_ERR_OUT_OF_MEMORY;
>  
> -	    tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
> +	    tmp = grub_cpu_to_le64 (sector << log_sector_size);
>  	    dev->iv_hash->init (ctx);
>  	    dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
>  	    dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
> @@ -281,15 +282,27 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
> -	  iv[1] = grub_cpu_to_le32 (sector >> GRUB_TYPE_BITS (iv[0]));
> -	  /* FALLTHROUGH */
>  	case GRUB_CRYPTODISK_MODE_IV_PLAIN:
> -	  iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0]));
> +	  /*
> +	   * The IV is a 32 or 64 bit value of the dm-crypt native sector
> +	   * number. If using 32 bit IV mode, zero out the most significant
> +	   * 32 bits.
> +	   */
> +	  {
> +	    grub_uint64_t iv64;
> +
> +	    iv64 = grub_cpu_to_le64 (sector << (log_sector_size
> +						 - GRUB_CRYPTODISK_IV_LOG_SIZE));
> +	    grub_set_unaligned64 (iv, iv64);
> +	    if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN)
> +	      iv[1] = 0;
> +	  }
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
> +	  /* The IV is the 64 bit byte offset of the sector. */
>  	  iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1])
> -					       - dev->log_sector_size));
> -	  iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
> +					       - log_sector_size));
> +	  iv[0] = grub_cpu_to_le32 ((sector << log_sector_size)
>  				    & GRUB_TYPE_U_MAX (iv[0]));
>  	  break;
>  	case GRUB_CRYPTODISK_MODE_IV_BENBI:
> @@ -312,10 +325,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_CBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size), iv);
> +					   (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -323,10 +336,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_PCBC:
>  	  if (do_encrypt)
>  	    err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  else
>  	    err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
> -					    (1U << dev->log_sector_size), iv);
> +					    (1U << log_sector_size), iv);
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -338,7 +351,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (err)
>  	      return err;
>  	    
> -	    for (j = 0; j < (1U << dev->log_sector_size);
> +	    for (j = 0; j < (1U << log_sector_size);
>  		 j += dev->cipher->cipher->blocksize)
>  	      {
>  		grub_crypto_xor (data + i + j, data + i + j, iv,
> @@ -369,11 +382,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	    if (do_encrypt)
>  	      err = grub_crypto_ecb_encrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    else
>  	      err = grub_crypto_ecb_decrypt (dev->cipher, data + i, 
>  					     data + i,
> -					     (1U << dev->log_sector_size));
> +					     (1U << log_sector_size));
>  	    if (err)
>  	      return err;
>  	    lrw_xor (&sec, dev, data + i);
> @@ -382,10 +395,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  	case GRUB_CRYPTODISK_MODE_ECB:
>  	  if (do_encrypt)
>  	    err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  else
>  	    err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
> -					   (1U << dev->log_sector_size));
> +					   (1U << log_sector_size));
>  	  if (err)
>  	    return err;
>  	  break;
> @@ -400,9 +413,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector)
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size)
>  {
> -  return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
> +  return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0);
>  }
>  
>  grub_err_t
> @@ -767,7 +780,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
>      }
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
>  					size << disk->log_sector_size,
> -					sector, 0);
> +					sector, dev->log_sector_size, 0);
>    return grub_crypto_gcry_error (gcry_err);
>  }
>  
> @@ -808,7 +821,7 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
>  
>    gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
>  					size << disk->log_sector_size,
> -					sector, 1);
> +					sector, disk->log_sector_size, 1);
>    if (gcry_err)
>      {
>        grub_free (tmp);
> diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
> index 5fc79d880..13103ea6a 100644
> --- a/grub-core/disk/luks.c
> +++ b/grub-core/disk/luks.c
> @@ -124,7 +124,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
>        return NULL;
>    newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset);
>    newdev->source_disk = NULL;
> -  newdev->log_sector_size = 9;
> +  newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE;
>    newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors;
>    grub_memcpy (newdev->uuid, uuid, sizeof (uuid));
>    newdev->modname = "luks";
> @@ -247,7 +247,8 @@ luks_recover_key (grub_disk_t source,
>  	  return err;
>  	}
>  
> -      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
> +      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0,
> +					  GRUB_LUKS1_LOG_SECTOR_SIZE);
>        if (gcry_err)
>  	{
>  	  grub_free (split_key);
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 429a4cfa1..9abcb1c94 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -504,7 +504,12 @@ luks2_decrypt_key (grub_uint8_t *out_key,
>        goto err;
>      }
>  
> -  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0);
> +  /*
> +   * The key slots area is always encrypted in 512-byte sectors,
> +   * regardless of encrypted data sector size.
> +   */
> +  gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0,
> +				      GRUB_LUKS1_LOG_SECTOR_SIZE);
>    if (gcry_ret)
>      {
>        ret = grub_crypto_gcry_error (gcry_ret);
> diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
> index c9bf7597a..938912cf3 100644
> --- a/include/grub/cryptodisk.h
> +++ b/include/grub/cryptodisk.h
> @@ -48,6 +48,12 @@ typedef enum
>  
>  #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71
>  
> +/* LUKS1 specification defines the block size to always be 512 bytes. */
> +#define GRUB_LUKS1_LOG_SECTOR_SIZE 9
> +
> +/* By default dm-crypt increments the IV every 512 bytes. */
> +#define GRUB_CRYPTODISK_IV_LOG_SIZE 9
> +
>  #define GRUB_CRYPTODISK_GF_LOG_SIZE 7
>  #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE)
>  #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
> @@ -144,7 +150,7 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev,
>  gcry_err_code_t
>  grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
>  			 grub_uint8_t * data, grub_size_t len,
> -			 grub_disk_addr_t sector);
> +			 grub_disk_addr_t sector, grub_size_t log_sector_size);
>  grub_err_t
>  grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
>  			grub_disk_t source);
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 15/18] luks2: Error check segment.sector_size
  2020-12-08 22:45           ` [PATCH v8 15/18] luks2: Error check segment.sector_size Glenn Washburn
  2020-12-10 16:08             ` Daniel Kiper
@ 2020-12-12  8:16             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:16 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:46PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index 8cb11e899..c737797b9 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -629,6 +629,17 @@ luks2_recover_key (grub_disk_t source,
>  
>        grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T"\"\n", keyslot.idx);
>  
> +      /* Sector size should be one of 512, 1024, 2048, or 4096. */
> +      if (!(segment.sector_size == 512 || segment.sector_size == 1024 ||
> +	    segment.sector_size == 2048 || segment.sector_size == 4096))
> +	{
> +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\" sector"
> +				 " size %"PRIuGRUB_UINT64_T" is not one of"
> +				 " 512, 1024, 2048, or 4096\n",
> +				 segment.idx, segment.sector_size);
> +	  continue;
> +	}
> +
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
>        crypt->log_sector_size = sizeof (unsigned int) * 8
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 16/18] mips: Enable __clzdi2()
  2020-12-08 22:45           ` [PATCH v8 16/18] mips: Enable __clzdi2() Glenn Washburn
  2020-12-10 16:09             ` Daniel Kiper
@ 2020-12-12  8:16             ` Patrick Steinhardt
  1 sibling, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:16 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:47PM -0600, Glenn Washburn wrote:
> This patch is similiar to commit 9dab2f51e (sparc: Enable __clzsi2() and
> __clzdi2()) but for MIPS target and __clzdi2 only, __clzsi2 was already
> enabled.
> 
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Suggested-by: Daniel Kiper <dkiper@net-space.pl>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/kern/compiler-rt.c | 2 +-
>  include/grub/compiler-rt.h   | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c
> index a464200c6..2057c2e0c 100644
> --- a/grub-core/kern/compiler-rt.c
> +++ b/grub-core/kern/compiler-rt.c
> @@ -448,7 +448,7 @@ __clzsi2 (grub_uint32_t val)
>  }
>  #endif
>  
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  __clzdi2 (grub_uint64_t val)
>  {
> diff --git a/include/grub/compiler-rt.h b/include/grub/compiler-rt.h
> index 7591980b4..17828b322 100644
> --- a/include/grub/compiler-rt.h
> +++ b/include/grub/compiler-rt.h
> @@ -115,7 +115,7 @@ int
>  EXPORT_FUNC (__clzsi2) (grub_uint32_t val);
>  #endif
>  
> -#if defined(__riscv) || defined(__sparc__)
> +#if defined(__mips__) || defined(__riscv) || defined(__sparc__)
>  int
>  EXPORT_FUNC (__clzdi2) (grub_uint64_t val);
>  #endif
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers
  2020-12-08 22:45           ` [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
@ 2020-12-12  8:17             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:17 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:48PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  include/grub/misc.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/include/grub/misc.h b/include/grub/misc.h
> index 780a34e90..73a514eb1 100644
> --- a/include/grub/misc.h
> +++ b/include/grub/misc.h
> @@ -482,4 +482,7 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
>  #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
>  #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
>  
> +#define grub_log2ull(n) (GRUB_TYPE_BITS (grub_uint64_t) \
> +                         - __builtin_clzll (n) - 1)
> +
>  #endif /* ! GRUB_MISC_HEADER */
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability
  2020-12-08 22:45           ` [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
@ 2020-12-12  8:18             ` Patrick Steinhardt
  0 siblings, 0 replies; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:18 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Daniel Kiper, Daniel Kiper

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

On Tue, Dec 08, 2020 at 04:45:49PM -0600, Glenn Washburn wrote:
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Reviewed-by: Patrick Steinhardt <ps@pks.im>

> ---
>  grub-core/disk/luks2.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> index c737797b9..31b51f1d4 100644
> --- a/grub-core/disk/luks2.c
> +++ b/grub-core/disk/luks2.c
> @@ -642,8 +642,7 @@ luks2_recover_key (grub_disk_t source,
>  
>        /* Set up disk according to keyslot's segment. */
>        crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL);
> -      crypt->log_sector_size = sizeof (unsigned int) * 8
> -		- __builtin_clz ((unsigned int) segment.sector_size) - 1;
> +      crypt->log_sector_size = grub_log2ull (segment.sector_size);
>        /* Set to the source disk size, which is the maximum we allow. */
>        max_crypt_sectors = grub_disk_convert_sector(source,
>  						   source->total_sectors,
> -- 
> 2.27.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-12-10 16:20           ` [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux Daniel Kiper
@ 2020-12-12  8:20             ` Patrick Steinhardt
  2020-12-12 14:40               ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12  8:20 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: Glenn Washburn, grub-devel

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

On Thu, Dec 10, 2020 at 05:20:59PM +0100, Daniel Kiper wrote:
> On Tue, Dec 08, 2020 at 04:45:31PM -0600, Glenn Washburn wrote:
> > This patch series, fixes issues with v7 series. Some of those patches had
> > changes applied to the wrong patch. The added structure member was renamed
> > again, this time to idx. And there is an added patch that renames some json
> > index variables to note that they are such.
> >
> > Glenn
> >
> > Glenn Washburn (18):
> >   disk: Rename grub_disk_get_size to grub_disk_native_sectors
> >   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
> >   whitespace: convert 8 spaces to tabs
> >   luks2: Remove unused argument in grub_error
> >   luks2: Make sure all fields of output argument in luks2_parse_digest()
> >     are written to
> >   luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
> >   luks2: Use more intuitive object name instead of json index in user
> >     messages
> >   luks2: Rename json index variables to names that they are obviously
> >     json indexes
> >   luks2: Add string "index" to user strings using a json index.
> >   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
> >   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
> >   luks2: grub_cryptodisk_t->total_sectors is the max number of device
> >     native sectors
> >   cryptodisk: Properly handle non-512 byte sized sectors
> >   luks2: Better error handling when setting up the cryptodisk
> >   luks2: Error check segment.sector_size
> >   mips: Enable __clzdi2()
> >   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
> >     integers
> >   luks2: Use grub_log2ull to calculate log_sector_size and improve
> >     readability
> 
> I will get all the patches except #14 and maybe some changes after that
> one which does not apply due to lack of it.
> 
> Thank you for doing the work!
> 
> Daniel

For what it's worth, I've also gone through all patches except 14 and
added by RBs. Thanks!

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-12-12  8:20             ` Patrick Steinhardt
@ 2020-12-12 14:40               ` Daniel Kiper
  2020-12-12 17:36                 ` Patrick Steinhardt
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-12 14:40 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Glenn Washburn

On Sat, Dec 12, 2020 at 09:20:24AM +0100, Patrick Steinhardt wrote:
> On Thu, Dec 10, 2020 at 05:20:59PM +0100, Daniel Kiper wrote:
> > On Tue, Dec 08, 2020 at 04:45:31PM -0600, Glenn Washburn wrote:
> > > This patch series, fixes issues with v7 series. Some of those patches had
> > > changes applied to the wrong patch. The added structure member was renamed
> > > again, this time to idx. And there is an added patch that renames some json
> > > index variables to note that they are such.
> > >
> > > Glenn
> > >
> > > Glenn Washburn (18):
> > >   disk: Rename grub_disk_get_size to grub_disk_native_sectors
> > >   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
> > >   whitespace: convert 8 spaces to tabs
> > >   luks2: Remove unused argument in grub_error
> > >   luks2: Make sure all fields of output argument in luks2_parse_digest()
> > >     are written to
> > >   luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
> > >   luks2: Use more intuitive object name instead of json index in user
> > >     messages
> > >   luks2: Rename json index variables to names that they are obviously
> > >     json indexes
> > >   luks2: Add string "index" to user strings using a json index.
> > >   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
> > >   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
> > >   luks2: grub_cryptodisk_t->total_sectors is the max number of device
> > >     native sectors
> > >   cryptodisk: Properly handle non-512 byte sized sectors
> > >   luks2: Better error handling when setting up the cryptodisk
> > >   luks2: Error check segment.sector_size
> > >   mips: Enable __clzdi2()
> > >   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
> > >     integers
> > >   luks2: Use grub_log2ull to calculate log_sector_size and improve
> > >     readability
> >
> > I will get all the patches except #14 and maybe some changes after that
> > one which does not apply due to lack of it.

Thanks! However, I have pushed some of these patches before you did review.

Daniel


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

* Re: [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk
  2020-12-12  1:10               ` Glenn Washburn
@ 2020-12-12 15:19                 ` Daniel Kiper
  2020-12-15 22:23                   ` Glenn Washburn
  0 siblings, 1 reply; 289+ messages in thread
From: Daniel Kiper @ 2020-12-12 15:19 UTC (permalink / raw)
  To: Glenn Washburn; +Cc: grub-devel, Patrick Steinhardt

On Fri, Dec 11, 2020 at 07:10:18PM -0600, Glenn Washburn wrote:
> On Thu, 10 Dec 2020 17:07:07 +0100
> Daniel Kiper <dkiper@net-space.pl> wrote:
>
> > On Tue, Dec 08, 2020 at 04:45:45PM -0600, Glenn Washburn wrote:
> > > First, check to make sure that source disk has a known size. If
> > > not, print debug message and return error. There are 4 cases where
> > > GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk, and
> > > uboot), and in all those cases processing continues. So this is
> > > probably a bit conservative. However, 3 of the cases seem
> > > pathological, and the other, biosdisk, happens when booting from a
> > > cd. Since I doubt booting from a LUKS2 volume on a cd is a big use
> > > case, we'll error until someone complains.
> > >
> > > Do some sanity checking on data coming from the luks header. If
> > > segment.size is "dynamic", verify that the offset is not past the
> > > end of disk. Otherwise, check for errors from grub_strtoull when
> > > converting segment size from string. If a GRUB_ERR_BAD_NUMBER error
> > > was returned, then the string was not a valid parsable number, so
> > > skip the key. If GRUB_ERR_OUT_OF_RANGE was returned, then there was
> > > an overflow in converting to a 64-bit unsigned integer. So this
> > > could be a very large disk (perhaps large raid array). In this
> > > case, we want to continue to try to use this key, but only allow
> > > access up to the end of the source disk.
> > >
> > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > ---
> > >  grub-core/disk/luks2.c | 84
> > > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h    |
> > > 17 +++++++++ 2 files changed, 98 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > index 9abcb1c94..8cb11e899 100644
> > > --- a/grub-core/disk/luks2.c
> > > +++ b/grub-core/disk/luks2.c
> > > @@ -600,12 +600,26 @@ luks2_recover_key (grub_disk_t source,
> > >        goto err;
> > >      }
> > >
> > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > +    {
> > > +      /* FIXME: Allow use of source disk, and maybe cause errors
> > > in read. */
> > > +      grub_dprintf ("luks2", "Source disk %s has an unknown size, "
> > > +			     "conservatively returning error\n",
> > > source->name);
> > > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > > source device");
> > > +      goto err;
> > > +    }
> > > +
> > >    /* Try all keyslot */
> > >    for (json_idx = 0; json_idx < size; json_idx++)
> > >      {
> > > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > > +
> > > +      grub_errno = GRUB_ERR_NONE;
> > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment, json,
> > > json_idx); if (ret)
> > >  	goto err;
> > > +      if (grub_errno != GRUB_ERR_NONE)
> > > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d from
> > > luks2_get_keyslot\n", grub_errno);
> > >
> > >        if (keyslot.priority == 0)
> > >  	{
> > > @@ -619,11 +633,75 @@ luks2_recover_key (grub_disk_t source,
> > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > > (unsigned int) * 8
> > >  		- __builtin_clz ((unsigned int)
> > > segment.sector_size) - 1;
> > > +      /* Set to the source disk size, which is the maximum we
> > > allow. */
> > > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > > +
> > > source->total_sectors,
> > > +
> > > crypt->log_sector_size); +
> > > +      if (max_crypt_sectors < crypt->offset_sectors)
> > > +	{
> > > +	  grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T"\"
> > > has offset"
> > > +				 " %"PRIuGRUB_UINT64_T" which is
> > > greater than"
> > > +				 " source disk size
> > > %"PRIuGRUB_UINT64_T","
> > > +				 " skipping\n",
> > > +				 segment.idx,
> > > crypt->offset_sectors,
> > > +				 max_crypt_sectors);
> > > +	  continue;
> > > +	}
> > > +
> > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > (crypt->log_sector_size - source->log_sector_size))
> > > -			       - crypt->offset_sectors;
> > > +	crypt->total_sectors = max_crypt_sectors -
> > > crypt->offset_sectors; else
> > > -	crypt->total_sectors = grub_strtoull (segment.size, NULL,
> > > 10) >> crypt->log_sector_size;
> > > +	{
> > > +	  grub_errno = GRUB_ERR_NONE;
> > > +	  /* Convert segment.size to sectors, rounding up to
> > > nearest sector */
> > > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > > NULL, 10);
> > > +	  crypt->total_sectors = ALIGN_UP (crypt->total_sectors,
> > > +					   1 <<
> > > crypt->log_sector_size);
> > > +	  crypt->total_sectors >>= crypt->log_sector_size;
> > > +
> > > +	  if (grub_errno == GRUB_ERR_NONE)
> > > +	    ;
> > > +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> > > +	    {
> > > +	      grub_dprintf ("luks2", "Segment
> > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > +				     " \"%s\" is not a parsable
> > > number\n",
> > > +				     segment.idx, segment.size);
> > > +	      continue;
> > > +	    }
> > > +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > > +	    {
> > > +	      /*
> > > +	       * There was an overflow in parsing segment.size, so
> > > disk must
> > > +	       * be very large or the string is incorrect.
> > > +	       */
> > > +	      grub_dprintf ("luks2", "Segment
> > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > +				     " %s overflowed 64-bit
> > > unsigned integer,"
> > > +				     " the end of the crypto
> > > device will be"
> > > +				     " inaccessible\n",
> > > +				     segment.idx, segment.size);
> > > +	      if (crypt->total_sectors > max_crypt_sectors)
> >
> > I think this if is bogus. You should clamp crypt->total_sectors
> > without any checks here.
>
> Actually, I wouldn't call this a clamp because in the overflow case
> crypt->total_sectors always equals 0.  I just realized this, and its
> because grub_strtoull will return 2^64-1 thus causing the following
> ALIGN_UP to overflow returning 0.  Suffice to say that's not what we
> want. My original intent was what happened before the ALIGN_UP code was
> introduced, which would ALIGN_DOWN.

Ugh... Right. That is why I still think you should do further calculations
on value returned from grub_strtoull() if grub_errno == GRUB_ERR_NONE only.
I understand that then crypt->total_sectors does not contain total sectors
for a while but you can rectify this a bit by putting short comment
before grub_strtoull() call.

> Here's an example illustrating why I wanted and still think the intent
> of this check is reasonable. Suppose we have a disk size 2^67 bytes
> with 512 byte (2^9) sized sectors. It will have 2^58 sectors. Further
> suppose, there is a LUKS volume with size 2^65 bytes starting at the
> beginning and a sector size of 4096 bytes (2^12). This will cause an
> overflow, so grub_strtoull will return 2^64-1, this should have us set
> crypt->total_sectors to 2^52-1. Since we don't know how much the
> overflow is (1 byte or 1 terabyte), we don't know how many more sectors
> til the end of the LUKS encrypted area. In this case max_crypt_sectors
> will be 2^(58+9-12) => 2^57 sectors.  So here we see that
> crypt->total_sectors < max_crypt_sectors in the overflow case.  If we
> do as you suggest crypt->total_sectors will be set to 2^57, and thus
> it will be valid to read past the end of the encrypted data (ie. block
> 2^56 of the 4k sector crypt will be a sector starting at byte 2^68,
> which is more than the 2^65 byte size volume).
>
> On the one hand, I like your suggestion because it allows reading all
> possible encrypted data, at the cost of reading, decrypting, and
> returning non-encrypted data (ie random garbage).  While keeping the
> check, will prevent returning garbage at the cost of not allowing
> access to all encrypted sectors. I think we should keep the check and
> document a known limitation of 2^64 byte maximum sized LUKS volumes.
> And that larger sized volumes can be read only up to byte 2^64.

If think the code should look like this:

  /*
   * ...a comment saying what crypt->total_sectors contains
   * and why LUKS2 volumes larger than 2^64 does not work...
   */
  crypt->total_sectors = grub_strtoull (segment.size,  NULL, 10);

  if (grub_errno == GRUB_ERR_NONE)
    {
      crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 << crypt->log_sector_size);
      crypt->total_sectors >>= crypt->log_sector_size;
    }
  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
    {
      ...
      continue;
    }

  if (grub_errno == GRUB_ERR_OUT_OF_RANGE ||
      !crypt->total_sectors ||
      crypt->total_sectors > max_crypt_sectors)
    {
      ...
      continue;
      /*
       * Yes, I think we should not guess crypt->total_sectors
       * value and always fail. It seems safer.
       */
    }

Daniel


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

* Re: [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-12-12 14:40               ` Daniel Kiper
@ 2020-12-12 17:36                 ` Patrick Steinhardt
  2020-12-14 12:13                   ` Daniel Kiper
  0 siblings, 1 reply; 289+ messages in thread
From: Patrick Steinhardt @ 2020-12-12 17:36 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Glenn Washburn

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

On Sat, Dec 12, 2020 at 03:40:30PM +0100, Daniel Kiper wrote:
> On Sat, Dec 12, 2020 at 09:20:24AM +0100, Patrick Steinhardt wrote:
> > On Thu, Dec 10, 2020 at 05:20:59PM +0100, Daniel Kiper wrote:
> > > On Tue, Dec 08, 2020 at 04:45:31PM -0600, Glenn Washburn wrote:
> > > > This patch series, fixes issues with v7 series. Some of those patches had
> > > > changes applied to the wrong patch. The added structure member was renamed
> > > > again, this time to idx. And there is an added patch that renames some json
> > > > index variables to note that they are such.
> > > >
> > > > Glenn
> > > >
> > > > Glenn Washburn (18):
> > > >   disk: Rename grub_disk_get_size to grub_disk_native_sectors
> > > >   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
> > > >   whitespace: convert 8 spaces to tabs
> > > >   luks2: Remove unused argument in grub_error
> > > >   luks2: Make sure all fields of output argument in luks2_parse_digest()
> > > >     are written to
> > > >   luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
> > > >   luks2: Use more intuitive object name instead of json index in user
> > > >     messages
> > > >   luks2: Rename json index variables to names that they are obviously
> > > >     json indexes
> > > >   luks2: Add string "index" to user strings using a json index.
> > > >   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
> > > >   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
> > > >   luks2: grub_cryptodisk_t->total_sectors is the max number of device
> > > >     native sectors
> > > >   cryptodisk: Properly handle non-512 byte sized sectors
> > > >   luks2: Better error handling when setting up the cryptodisk
> > > >   luks2: Error check segment.sector_size
> > > >   mips: Enable __clzdi2()
> > > >   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
> > > >     integers
> > > >   luks2: Use grub_log2ull to calculate log_sector_size and improve
> > > >     readability
> > >
> > > I will get all the patches except #14 and maybe some changes after that
> > > one which does not apply due to lack of it.
> 
> Thanks! However, I have pushed some of these patches before you did review.
> 
> Daniel

I thought as much, though I didn't check. I don't really mind, thought
it might make sense to send them out in any case.

Patrick

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux
  2020-12-12 17:36                 ` Patrick Steinhardt
@ 2020-12-14 12:13                   ` Daniel Kiper
  0 siblings, 0 replies; 289+ messages in thread
From: Daniel Kiper @ 2020-12-14 12:13 UTC (permalink / raw)
  To: Patrick Steinhardt; +Cc: grub-devel, Glenn Washburn

On Sat, Dec 12, 2020 at 06:36:58PM +0100, Patrick Steinhardt wrote:
> On Sat, Dec 12, 2020 at 03:40:30PM +0100, Daniel Kiper wrote:
> > On Sat, Dec 12, 2020 at 09:20:24AM +0100, Patrick Steinhardt wrote:
> > > On Thu, Dec 10, 2020 at 05:20:59PM +0100, Daniel Kiper wrote:
> > > > On Tue, Dec 08, 2020 at 04:45:31PM -0600, Glenn Washburn wrote:
> > > > > This patch series, fixes issues with v7 series. Some of those patches had
> > > > > changes applied to the wrong patch. The added structure member was renamed
> > > > > again, this time to idx. And there is an added patch that renames some json
> > > > > index variables to note that they are such.
> > > > >
> > > > > Glenn
> > > > >
> > > > > Glenn Washburn (18):
> > > > >   disk: Rename grub_disk_get_size to grub_disk_native_sectors
> > > > >   misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments
> > > > >   whitespace: convert 8 spaces to tabs
> > > > >   luks2: Remove unused argument in grub_error
> > > > >   luks2: Make sure all fields of output argument in luks2_parse_digest()
> > > > >     are written to
> > > > >   luks2: Add idx member to struct grub_luks2_keyslot/segment/digest
> > > > >   luks2: Use more intuitive object name instead of json index in user
> > > > >     messages
> > > > >   luks2: Rename json index variables to names that they are obviously
> > > > >     json indexes
> > > > >   luks2: Add string "index" to user strings using a json index.
> > > > >   cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals
> > > > >   cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals
> > > > >   luks2: grub_cryptodisk_t->total_sectors is the max number of device
> > > > >     native sectors
> > > > >   cryptodisk: Properly handle non-512 byte sized sectors
> > > > >   luks2: Better error handling when setting up the cryptodisk
> > > > >   luks2: Error check segment.sector_size
> > > > >   mips: Enable __clzdi2()
> > > > >   misc: Add grub_log2ull macro for calculating log base 2 of 64-bit
> > > > >     integers
> > > > >   luks2: Use grub_log2ull to calculate log_sector_size and improve
> > > > >     readability
> > > >
> > > > I will get all the patches except #14 and maybe some changes after that
> > > > one which does not apply due to lack of it.
> >
> > Thanks! However, I have pushed some of these patches before you did review.
> >
> > Daniel
>
> I thought as much, though I didn't check. I don't really mind, thought
> it might make sense to send them out in any case.

Yeah, at least I am more sure I did not miss any mistakes... :-)

Daniel


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

* Re: [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk
  2020-12-12 15:19                 ` Daniel Kiper
@ 2020-12-15 22:23                   ` Glenn Washburn
  0 siblings, 0 replies; 289+ messages in thread
From: Glenn Washburn @ 2020-12-15 22:23 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: grub-devel, Patrick Steinhardt

On Sat, 12 Dec 2020 16:19:18 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Fri, Dec 11, 2020 at 07:10:18PM -0600, Glenn Washburn wrote:
> > On Thu, 10 Dec 2020 17:07:07 +0100
> > Daniel Kiper <dkiper@net-space.pl> wrote:
> >
> > > On Tue, Dec 08, 2020 at 04:45:45PM -0600, Glenn Washburn wrote:
> > > > First, check to make sure that source disk has a known size. If
> > > > not, print debug message and return error. There are 4 cases
> > > > where GRUB_DISK_SIZE_UNKNOWN is set (biosdisk, obdisk, ofdisk,
> > > > and uboot), and in all those cases processing continues. So
> > > > this is probably a bit conservative. However, 3 of the cases
> > > > seem pathological, and the other, biosdisk, happens when
> > > > booting from a cd. Since I doubt booting from a LUKS2 volume on
> > > > a cd is a big use case, we'll error until someone complains.
> > > >
> > > > Do some sanity checking on data coming from the luks header. If
> > > > segment.size is "dynamic", verify that the offset is not past
> > > > the end of disk. Otherwise, check for errors from grub_strtoull
> > > > when converting segment size from string. If a
> > > > GRUB_ERR_BAD_NUMBER error was returned, then the string was not
> > > > a valid parsable number, so skip the key. If
> > > > GRUB_ERR_OUT_OF_RANGE was returned, then there was an overflow
> > > > in converting to a 64-bit unsigned integer. So this could be a
> > > > very large disk (perhaps large raid array). In this case, we
> > > > want to continue to try to use this key, but only allow access
> > > > up to the end of the source disk.
> > > >
> > > > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > > > ---
> > > >  grub-core/disk/luks2.c | 84
> > > > ++++++++++++++++++++++++++++++++++++++++-- include/grub/disk.h
> > > >   | 17 +++++++++ 2 files changed, 98 insertions(+), 3
> > > > deletions(-)
> > > >
> > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > index 9abcb1c94..8cb11e899 100644
> > > > --- a/grub-core/disk/luks2.c
> > > > +++ b/grub-core/disk/luks2.c
> > > > @@ -600,12 +600,26 @@ luks2_recover_key (grub_disk_t source,
> > > >        goto err;
> > > >      }
> > > >
> > > > +  if (source->total_sectors == GRUB_DISK_SIZE_UNKNOWN)
> > > > +    {
> > > > +      /* FIXME: Allow use of source disk, and maybe cause
> > > > errors in read. */
> > > > +      grub_dprintf ("luks2", "Source disk %s has an unknown
> > > > size, "
> > > > +			     "conservatively returning
> > > > error\n", source->name);
> > > > +      ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2
> > > > source device");
> > > > +      goto err;
> > > > +    }
> > > > +
> > > >    /* Try all keyslot */
> > > >    for (json_idx = 0; json_idx < size; json_idx++)
> > > >      {
> > > > +      typeof(source->total_sectors) max_crypt_sectors = 0;
> > > > +
> > > > +      grub_errno = GRUB_ERR_NONE;
> > > >        ret = luks2_get_keyslot (&keyslot, &digest, &segment,
> > > > json, json_idx); if (ret)
> > > >  	goto err;
> > > > +      if (grub_errno != GRUB_ERR_NONE)
> > > > +	  grub_dprintf ("luks2", "Ignoring unhandled error %d
> > > > from luks2_get_keyslot\n", grub_errno);
> > > >
> > > >        if (keyslot.priority == 0)
> > > >  	{
> > > > @@ -619,11 +633,75 @@ luks2_recover_key (grub_disk_t source,
> > > >        crypt->offset_sectors = grub_divmod64 (segment.offset,
> > > > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > > > (unsigned int) * 8
> > > >  		- __builtin_clz ((unsigned int)
> > > > segment.sector_size) - 1;
> > > > +      /* Set to the source disk size, which is the maximum we
> > > > allow. */
> > > > +      max_crypt_sectors = grub_disk_convert_sector(source,
> > > > +
> > > > source->total_sectors,
> > > > +
> > > > crypt->log_sector_size); +
> > > > +      if (max_crypt_sectors < crypt->offset_sectors)
> > > > +	{
> > > > +	  grub_dprintf ("luks2", "Segment
> > > > \"%"PRIuGRUB_UINT64_T"\" has offset"
> > > > +				 " %"PRIuGRUB_UINT64_T" which
> > > > is greater than"
> > > > +				 " source disk size
> > > > %"PRIuGRUB_UINT64_T","
> > > > +				 " skipping\n",
> > > > +				 segment.idx,
> > > > crypt->offset_sectors,
> > > > +				 max_crypt_sectors);
> > > > +	  continue;
> > > > +	}
> > > > +
> > > >        if (grub_strcmp (segment.size, "dynamic") == 0)
> > > > -	crypt->total_sectors = (grub_disk_get_size (source) >>
> > > > (crypt->log_sector_size - source->log_sector_size))
> > > > -			       - crypt->offset_sectors;
> > > > +	crypt->total_sectors = max_crypt_sectors -
> > > > crypt->offset_sectors; else
> > > > -	crypt->total_sectors = grub_strtoull (segment.size,
> > > > NULL, 10) >> crypt->log_sector_size;
> > > > +	{
> > > > +	  grub_errno = GRUB_ERR_NONE;
> > > > +	  /* Convert segment.size to sectors, rounding up to
> > > > nearest sector */
> > > > +	  crypt->total_sectors = grub_strtoull (segment.size,
> > > > NULL, 10);
> > > > +	  crypt->total_sectors = ALIGN_UP
> > > > (crypt->total_sectors,
> > > > +					   1 <<
> > > > crypt->log_sector_size);
> > > > +	  crypt->total_sectors >>= crypt->log_sector_size;
> > > > +
> > > > +	  if (grub_errno == GRUB_ERR_NONE)
> > > > +	    ;
> > > > +	  else if (grub_errno == GRUB_ERR_BAD_NUMBER)
> > > > +	    {
> > > > +	      grub_dprintf ("luks2", "Segment
> > > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > > +				     " \"%s\" is not a parsable
> > > > number\n",
> > > > +				     segment.idx,
> > > > segment.size);
> > > > +	      continue;
> > > > +	    }
> > > > +	  else if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
> > > > +	    {
> > > > +	      /*
> > > > +	       * There was an overflow in parsing
> > > > segment.size, so disk must
> > > > +	       * be very large or the string is incorrect.
> > > > +	       */
> > > > +	      grub_dprintf ("luks2", "Segment
> > > > \"%"PRIuGRUB_UINT64_T"\" size"
> > > > +				     " %s overflowed 64-bit
> > > > unsigned integer,"
> > > > +				     " the end of the crypto
> > > > device will be"
> > > > +				     " inaccessible\n",
> > > > +				     segment.idx,
> > > > segment.size);
> > > > +	      if (crypt->total_sectors > max_crypt_sectors)
> > >
> > > I think this if is bogus. You should clamp crypt->total_sectors
> > > without any checks here.
> >
> > Actually, I wouldn't call this a clamp because in the overflow case
> > crypt->total_sectors always equals 0.  I just realized this, and its
> > because grub_strtoull will return 2^64-1 thus causing the following
> > ALIGN_UP to overflow returning 0.  Suffice to say that's not what we
> > want. My original intent was what happened before the ALIGN_UP code
> > was introduced, which would ALIGN_DOWN.
> 
> Ugh... Right. That is why I still think you should do further
> calculations on value returned from grub_strtoull() if grub_errno ==
> GRUB_ERR_NONE only. I understand that then crypt->total_sectors does
> not contain total sectors for a while but you can rectify this a bit
> by putting short comment before grub_strtoull() call.
> 
> > Here's an example illustrating why I wanted and still think the
> > intent of this check is reasonable. Suppose we have a disk size
> > 2^67 bytes with 512 byte (2^9) sized sectors. It will have 2^58
> > sectors. Further suppose, there is a LUKS volume with size 2^65
> > bytes starting at the beginning and a sector size of 4096 bytes
> > (2^12). This will cause an overflow, so grub_strtoull will return
> > 2^64-1, this should have us set crypt->total_sectors to 2^52-1.
> > Since we don't know how much the overflow is (1 byte or 1
> > terabyte), we don't know how many more sectors til the end of the
> > LUKS encrypted area. In this case max_crypt_sectors will be
> > 2^(58+9-12) => 2^57 sectors.  So here we see that
> > crypt->total_sectors < max_crypt_sectors in the overflow case.  If
> > we do as you suggest crypt->total_sectors will be set to 2^57, and
> > thus it will be valid to read past the end of the encrypted data
> > (ie. block 2^56 of the 4k sector crypt will be a sector starting at
> > byte 2^68, which is more than the 2^65 byte size volume).
> >
> > On the one hand, I like your suggestion because it allows reading
> > all possible encrypted data, at the cost of reading, decrypting, and
> > returning non-encrypted data (ie random garbage).  While keeping the
> > check, will prevent returning garbage at the cost of not allowing
> > access to all encrypted sectors. I think we should keep the check
> > and document a known limitation of 2^64 byte maximum sized LUKS
> > volumes. And that larger sized volumes can be read only up to byte
> > 2^64.
> 
> If think the code should look like this:
> 
>   /*
>    * ...a comment saying what crypt->total_sectors contains
>    * and why LUKS2 volumes larger than 2^64 does not work...
>    */
>   crypt->total_sectors = grub_strtoull (segment.size,  NULL, 10);
> 
>   if (grub_errno == GRUB_ERR_NONE)
>     {
>       crypt->total_sectors = ALIGN_UP (crypt->total_sectors, 1 <<
> crypt->log_sector_size); crypt->total_sectors >>=
> crypt->log_sector_size; }

Now that ALIGN_UP is being used which we don't want in the
GRUB_ERR_OUT_OF_RANGE case, I'm ok with this. Although, if we just
continue in grub_strtoull error case as you suggest below, it doesn't
matter. And this actually doesn't prevent ALIGN_UP from potentially
overflowing crypt->total_sectors either, when segment.size is very
large. Perhaps we should check for that.

>   else if (grub_errno == GRUB_ERR_BAD_NUMBER)
>     {
>       ...
>       continue;
>     }
> 
>   if (grub_errno == GRUB_ERR_OUT_OF_RANGE ||
>       !crypt->total_sectors ||
>       crypt->total_sectors > max_crypt_sectors)
>     {
>       ...
>       continue;
>       /*
>        * Yes, I think we should not guess crypt->total_sectors
>        * value and always fail. It seems safer.
>        */

I agree this is safer, but its at the cost of using volumes over 2^64
bytes working at all. I think the question is how safe is it to allow
arbitrary disk read failures in grub. Ultimately I don't really like
continuing here, which is why I originally had the TODO, because it
prevents otherwise accessible drives from being accessible (admittedly
in an extremely rare case). Think about a 2^65 sized raid with LUKS on
top and LVM on top of that. But really you should probably not be
booting from that anyway. I think I'll add a TODO here, with a work
around suggesting not to use such large devices to boot from.

>     }

Glenn


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

end of thread, other threads:[~2020-12-15 22:23 UTC | newest]

Thread overview: 289+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-03 21:45 [PATCH 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
2020-10-03 21:45 ` [PATCH 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
2020-10-03 21:45 ` [PATCH 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
2020-10-03 21:45 ` [PATCH 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
2020-10-03 21:45 ` [PATCH 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
2020-10-03 21:45 ` [PATCH 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
2020-10-03 21:45 ` [PATCH 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-10-03 21:46 ` [PATCH 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-10-03 21:46 ` [PATCH 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
2020-10-03 21:46 ` [PATCH 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
2020-10-03 21:46 ` [PATCH 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
2020-10-03 22:55 ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Glenn Washburn
2020-10-03 22:55   ` [PATCH v2 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
2020-10-09  9:38     ` Patrick Steinhardt
2020-10-03 22:55   ` [PATCH v2 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
2020-10-03 22:55   ` [PATCH v2 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
2020-10-09  9:44     ` Patrick Steinhardt
2020-10-18 19:05       ` Glenn Washburn
2020-10-03 22:55   ` [PATCH v2 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
2020-10-09  9:45     ` Patrick Steinhardt
2020-10-03 22:55   ` [PATCH v2 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
2020-10-03 22:55   ` [PATCH v2 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-10-09  9:50     ` Patrick Steinhardt
2020-10-18 18:38       ` Glenn Washburn
2020-10-03 22:55   ` [PATCH v2 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-10-18 18:23     ` Glenn Washburn
2020-10-19 11:27       ` Daniel Kiper
2020-10-03 22:55   ` [PATCH v2 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
2020-10-09  9:55     ` Patrick Steinhardt
2020-10-03 22:55   ` [PATCH v2 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
2020-10-09  9:56     ` Patrick Steinhardt
2020-10-03 22:55   ` [PATCH v2 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
2020-10-09 10:00     ` Patrick Steinhardt
2020-10-19 16:27       ` Glenn Washburn
2020-10-23 17:46         ` Patrick Steinhardt
2020-10-09 10:01   ` [PATCH v2 00/10] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
2020-10-19 23:09     ` [PATCH v3 " Glenn Washburn
2020-10-19 23:09       ` [PATCH v3 01/10] luks2: Fix use of incorrect index and some grub_error() messages Glenn Washburn
2020-10-23 12:08         ` Daniel Kiper
2020-10-23 17:52           ` Patrick Steinhardt
2020-10-19 23:09       ` [PATCH v3 02/10] luks2: Improve readability in luks2_get_keyslot Glenn Washburn
2020-10-23 12:14         ` Daniel Kiper
2020-10-29 21:52           ` Glenn Washburn
2020-10-30 13:15             ` Daniel Kiper
2020-10-19 23:09       ` [PATCH v3 03/10] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
2020-10-23 17:55         ` Patrick Steinhardt
2020-10-19 23:09       ` [PATCH v3 04/10] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
2020-10-23 18:03         ` Patrick Steinhardt
2020-10-19 23:09       ` [PATCH v3 05/10] cryptodisk: Fix cipher IV mode 'plain64' always being set as 'plain' Glenn Washburn
2020-10-23 12:21         ` Daniel Kiper
2020-10-19 23:09       ` [PATCH v3 06/10] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-10-23 18:09         ` Patrick Steinhardt
2020-10-26 15:43           ` Daniel Kiper
2020-10-30 20:47         ` Daniel Kiper
2020-11-06 19:08           ` Glenn Washburn
2020-11-19 14:25             ` Daniel Kiper
2020-11-20  5:18               ` Glenn Washburn
2020-11-20 14:17                 ` Daniel Kiper
2020-11-20 23:28                   ` Glenn Washburn
2020-10-19 23:09       ` [PATCH v3 07/10] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-10-23 18:01         ` Patrick Steinhardt
2020-10-26 18:25           ` Glenn Washburn
2020-10-28 18:16             ` Patrick Steinhardt
2020-10-27 18:03         ` Daniel Kiper
2020-10-29 21:51           ` Glenn Washburn
2020-10-30 13:11             ` Daniel Kiper
2020-10-19 23:09       ` [PATCH v3 08/10] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
2020-10-23 17:58         ` Patrick Steinhardt
2020-10-27 18:06           ` Daniel Kiper
2020-10-19 23:09       ` [PATCH v3 09/10] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
2020-10-23 17:58         ` Patrick Steinhardt
2020-10-27 18:07           ` Daniel Kiper
2020-10-19 23:09       ` [PATCH v3 10/10] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
2020-10-23 18:01         ` Patrick Steinhardt
2020-10-27 18:09           ` Daniel Kiper
2020-10-27 19:25       ` [PATCH v3 00/10] Cryptodisk fixes for v2.06 redux Daniel Kiper
2020-11-02 15:56         ` Daniel Kiper
2020-11-03 18:50           ` Glenn Washburn
2020-11-04 12:44             ` Daniel Kiper
2020-11-07  4:44       ` [PATCH v4 00/15] " Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 01/15] cryptodisk: Rename total_length field in grub_cryptodisk_t to total_sectors Glenn Washburn
2020-11-15  9:37           ` Patrick Steinhardt
2020-11-16 16:22             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 02/15] cryptodisk: Rename offset in grub_cryptodisk_t to offset_sectors Glenn Washburn
2020-11-15  9:38           ` Patrick Steinhardt
2020-11-16 16:25             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 03/15] luks2: Rename source disk variabled named 'disk' to 'source' as in luks.c Glenn Washburn
2020-11-15  9:39           ` Patrick Steinhardt
2020-11-16 16:27             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 04/15] types: Define GRUB_CHAR_BIT based on compiler macro instead of using literal Glenn Washburn
2020-11-15  9:42           ` Patrick Steinhardt
2020-11-16 16:31             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 05/15] luks2: Use correct index variable when looping in luks2_get_keyslot Glenn Washburn
2020-11-15  9:43           ` Patrick Steinhardt
2020-11-16 16:35             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 06/15] luks2: Rename variable i to keyslot_idx " Glenn Washburn
2020-11-15  9:43           ` Patrick Steinhardt
2020-11-16 16:37             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 07/15] luks2: Rename index variable j to i Glenn Washburn
2020-11-15  9:44           ` Patrick Steinhardt
2020-11-16 16:38             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 08/15] luks2: Split idx into three variables: keyslot_key, digest_key, segment_key Glenn Washburn
2020-11-15  9:48           ` Patrick Steinhardt
2020-11-17 13:47             ` Daniel Kiper
2020-11-20  8:39               ` Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 09/15] luks2: Improve error messages in luks2_get_keyslot Glenn Washburn
2020-11-15  9:52           ` Patrick Steinhardt
2020-11-17 13:51             ` Daniel Kiper
2020-11-07  4:44         ` [PATCH v4 10/15] luks2: Use more intuitive keyslot key instead of index when naming keyslot Glenn Washburn
2020-11-15  9:55           ` Patrick Steinhardt
2020-11-20  8:40             ` Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 11/15] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-11-15  9:59           ` Patrick Steinhardt
2020-11-20  8:41             ` Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 12/15] luks2: grub_cryptodisk_t->total_length is the max number of device native sectors Glenn Washburn
2020-11-15 10:00           ` Patrick Steinhardt
2020-11-17 14:06           ` Daniel Kiper
2020-11-20  8:41             ` Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 13/15] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-11-15 10:07           ` Patrick Steinhardt
2020-11-20  8:42             ` Glenn Washburn
2020-11-22 12:30               ` Patrick Steinhardt
2020-11-07  4:44         ` [PATCH v4 14/15] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
2020-11-15 10:13           ` Patrick Steinhardt
2020-11-20  8:44             ` Glenn Washburn
2020-11-17 14:26           ` Daniel Kiper
2020-11-20  8:44             ` Glenn Washburn
2020-11-20 20:24               ` Daniel Kiper
2020-11-20 23:58                 ` Glenn Washburn
2020-11-07  4:44         ` [PATCH v4 15/15] luks2: Error check segment.sector_size Glenn Washburn
2020-11-15 10:42           ` Patrick Steinhardt
2020-11-17 14:28             ` Daniel Kiper
2020-11-17 14:34         ` [PATCH v4 00/15] Cryptodisk fixes for v2.06 redux Daniel Kiper
2020-11-23  5:23         ` [PATCH v5 00/11] " Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 01/11] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 02/11] luks: Use more intuitive slot key instead of index in user messages Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 03/11] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 04/11] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 05/11] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 06/11] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 07/11] luks2: Error check segment.sector_size Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 08/11] whitespace: convert 8 spaces to tabs Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 09/11] mips: Enable __clzdi2() Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 10/11] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
2020-11-23  5:23           ` [PATCH v5 11/11] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
2020-11-27  9:03         ` [PATCH v6 00/12] Cryptodisk fixes for v2.06 redux Glenn Washburn
2020-11-27  9:03           ` [PATCH v6 01/12] luks2: Add slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
2020-12-02 17:01             ` Daniel Kiper
2020-12-03  7:23               ` Glenn Washburn
2020-12-03 12:35                 ` Daniel Kiper
2020-12-03 16:46                   ` Glenn Washburn
2020-12-04 13:23                     ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 02/12] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
2020-12-02 17:23             ` Daniel Kiper
2020-12-03  7:24               ` Glenn Washburn
2020-12-03 12:39                 ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 03/12] luks2: Remove unused argument in grub_error Glenn Washburn
2020-12-02 17:24             ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 04/12] cryptodisk: Replace some literals with constants in grub_cryptodisk_endecrypt Glenn Washburn
2020-12-02 17:37             ` Daniel Kiper
2020-12-03  8:29               ` Glenn Washburn
2020-12-03 12:44                 ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 05/12] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
2020-12-02 17:56             ` Daniel Kiper
2020-12-03  8:54               ` Glenn Washburn
2020-12-03 12:45                 ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 06/12] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-12-03 13:04             ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 07/12] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
2020-12-03 13:31             ` Daniel Kiper
2020-12-03 16:24               ` Glenn Washburn
2020-12-04 13:19                 ` Daniel Kiper
2020-12-04 14:51                   ` Glenn Washburn
2020-11-27  9:03           ` [PATCH v6 08/12] luks2: Error check segment.sector_size Glenn Washburn
2020-12-03 13:52             ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 09/12] whitespace: convert 8 spaces to tabs Glenn Washburn
2020-12-03 13:53             ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 10/12] mips: Enable __clzdi2() Glenn Washburn
2020-12-03 14:00             ` Daniel Kiper
2020-12-03 15:58               ` Glenn Washburn
2020-12-04 13:07                 ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 11/12] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
2020-12-03 14:02             ` Daniel Kiper
2020-11-27  9:03           ` [PATCH v6 12/12] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
2020-12-03 14:13             ` Daniel Kiper
2020-12-04 16:43         ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Glenn Washburn
2020-12-04 16:43           ` [PATCH v7 01/17] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
2020-12-06 13:24             ` Patrick Steinhardt
2020-12-07 19:38             ` Daniel Kiper
2020-12-04 16:43           ` [PATCH v7 02/17] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
2020-12-06 13:24             ` Patrick Steinhardt
2020-12-07 19:50             ` Daniel Kiper
2020-12-04 16:43           ` [PATCH v7 03/17] luks2: Remove unused argument in grub_error Glenn Washburn
2020-12-06 13:25             ` Patrick Steinhardt
2020-12-07 19:52             ` Daniel Kiper
2020-12-08 17:45               ` Glenn Washburn
2020-12-08 18:32                 ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 04/17] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
2020-12-06 13:26             ` Patrick Steinhardt
2020-12-07 19:58             ` Daniel Kiper
2020-12-04 16:43           ` [PATCH v7 05/17] luks2: Add json_slot_key member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
2020-12-06 13:29             ` Patrick Steinhardt
2020-12-07 20:02               ` Daniel Kiper
2020-12-08  4:06                 ` Glenn Washburn
2020-12-08  6:38                   ` Patrick Steinhardt
2020-12-08 17:55                     ` Glenn Washburn
2020-12-04 16:43           ` [PATCH v7 06/17] luks2: Use more intuitive slot key instead of index in user messages Glenn Washburn
2020-12-06 13:31             ` Patrick Steinhardt
2020-12-07 20:15             ` Daniel Kiper
2020-12-08 17:56               ` Glenn Washburn
2020-12-04 16:43           ` [PATCH v7 07/17] luks2: Add string "index" to user strings using a json index Glenn Washburn
2020-12-06 13:31             ` Patrick Steinhardt
2020-12-07 20:17             ` Daniel Kiper
2020-12-04 16:43           ` [PATCH v7 08/17] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
2020-12-06 13:32             ` Patrick Steinhardt
2020-12-07 20:18             ` Daniel Kiper
2020-12-04 16:43           ` [PATCH v7 09/17] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
2020-12-06 13:33             ` Patrick Steinhardt
2020-12-07 20:22             ` Daniel Kiper
2020-12-08  4:06               ` Glenn Washburn
2020-12-04 16:43           ` [PATCH v7 10/17] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
2020-12-06 13:34             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 11/17] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-12-06 19:21             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 12/17] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
2020-12-06 19:35             ` Patrick Steinhardt
2020-12-08  4:04               ` Glenn Washburn
2020-12-08  6:41                 ` Patrick Steinhardt
2020-12-08  4:28             ` Glenn Washburn
2020-12-04 16:43           ` [PATCH v7 13/17] luks2: Error check segment.sector_size Glenn Washburn
2020-12-06 19:35             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 14/17] whitespace: convert 8 spaces to tabs Glenn Washburn
2020-12-06 13:35             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 15/17] mips: Enable __clzdi2() Glenn Washburn
2020-12-06 19:36             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 16/17] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
2020-12-06 13:36             ` Patrick Steinhardt
2020-12-04 16:43           ` [PATCH v7 17/17] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
2020-12-06 19:44             ` Patrick Steinhardt
2020-12-06 13:38           ` [PATCH v7 00/17] Cryptodisk fixes for v2.06 redux Patrick Steinhardt
2020-12-08 22:45         ` [PATCH v8 00/18] " Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 01/18] disk: Rename grub_disk_get_size to grub_disk_native_sectors Glenn Washburn
2020-12-09 17:39             ` Daniel Kiper
2020-12-08 22:45           ` [PATCH v8 02/18] misc: Add parentheses around ALIGN_UP and ALIGN_DOWN arguments Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 03/18] whitespace: convert 8 spaces to tabs Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 04/18] luks2: Remove unused argument in grub_error Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 05/18] luks2: Make sure all fields of output argument in luks2_parse_digest() are written to Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 06/18] luks2: Add idx member to struct grub_luks2_keyslot/segment/digest Glenn Washburn
2020-12-09 18:02             ` Daniel Kiper
2020-12-12  8:07             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 07/18] luks2: Use more intuitive object name instead of json index in user messages Glenn Washburn
2020-12-09 18:05             ` Daniel Kiper
2020-12-12  8:09             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 08/18] luks2: Rename json index variables to names that they are obviously json indexes Glenn Washburn
2020-12-09 18:07             ` Daniel Kiper
2020-12-12  8:10             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 09/18] luks2: Add string "index" to user strings using a json index Glenn Washburn
2020-12-09 18:09             ` Daniel Kiper
2020-12-12  8:11             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 10/18] cryptodisk: Add macro GRUB_TYPE_BITS() to replace some literals Glenn Washburn
2020-12-09 18:12             ` Daniel Kiper
2020-12-12  8:12             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 11/18] cryptodisk: Add macros GRUB_TYPE_U_MAX/MIN(type) to replace literals Glenn Washburn
2020-12-10 14:51             ` Daniel Kiper
2020-12-12  8:13             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 12/18] luks2: grub_cryptodisk_t->total_sectors is the max number of device native sectors Glenn Washburn
2020-12-12  8:14             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 13/18] cryptodisk: Properly handle non-512 byte sized sectors Glenn Washburn
2020-12-12  8:15             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 14/18] luks2: Better error handling when setting up the cryptodisk Glenn Washburn
2020-12-10 16:07             ` Daniel Kiper
2020-12-12  1:10               ` Glenn Washburn
2020-12-12 15:19                 ` Daniel Kiper
2020-12-15 22:23                   ` Glenn Washburn
2020-12-08 22:45           ` [PATCH v8 15/18] luks2: Error check segment.sector_size Glenn Washburn
2020-12-10 16:08             ` Daniel Kiper
2020-12-12  8:16             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 16/18] mips: Enable __clzdi2() Glenn Washburn
2020-12-10 16:09             ` Daniel Kiper
2020-12-12  8:16             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 17/18] misc: Add grub_log2ull macro for calculating log base 2 of 64-bit integers Glenn Washburn
2020-12-12  8:17             ` Patrick Steinhardt
2020-12-08 22:45           ` [PATCH v8 18/18] luks2: Use grub_log2ull to calculate log_sector_size and improve readability Glenn Washburn
2020-12-12  8:18             ` Patrick Steinhardt
2020-12-10 16:20           ` [PATCH v8 00/18] Cryptodisk fixes for v2.06 redux Daniel Kiper
2020-12-12  8:20             ` Patrick Steinhardt
2020-12-12 14:40               ` Daniel Kiper
2020-12-12 17:36                 ` Patrick Steinhardt
2020-12-14 12:13                   ` Daniel Kiper

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.