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.
Signed-off-by: Glenn Washburn <developm...@efficientek.com> --- grub-core/disk/luks2.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c index 9f58780a2..41329f745 100644 --- a/grub-core/disk/luks2.c +++ b/grub-core/disk/luks2.c @@ -416,7 +416,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; @@ -602,9 +602,14 @@ 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 (source) - crypt->offset; + /* + * Convert to cryptodisk sized sectors from source disk sized sectors + * before subtracting the offset, which is in cryptodisk sized sectors. + */ + crypt->total_length = (grub_disk_get_size (source) >> (crypt->log_sector_size - source->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, source, crypt, &keyslot, (const grub_uint8_t *) passphrase, grub_strlen (passphrase)); -- 2.25.1 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel