Commit Graph

28 Commits

Author SHA1 Message Date
Miguel Ángel Arruga Vivas
837fe48deb i18n: Format large integers before the translation message
The GNU gettext only supports the ISO C99 macros for integral
types. If there is a need to use unsupported formatting macros,
e.g. PRIuGRUB_UINT64_T, according to [1] the number to a string
conversion should be separated from the code printing message
requiring the internationalization. So, the function grub_snprintf()
is used to print the numeric values to an intermediate buffer and
the internationalized message contains a string format directive.

[1] https://www.gnu.org/software/gettext/manual/html_node/Preparing-Strings.html#No-string-concatenation

Signed-off-by: Miguel Ángel Arruga Vivas <rosen644835@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-04-13 17:16:04 +02:00
Glenn Washburn
39cfb3eb5c style: Format string macro should have a space between quotes
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2021-03-10 15:23:34 +01:00
Glenn Washburn
ec46685ed4 luks2: Use grub_log2ull() to calculate log_sector_size and improve readability
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-18 23:15:05 +01:00
Glenn Washburn
9c3149a2f2 luks2: Better error handling when setting up the cryptodisk
Do some sanity checking on data coming from the LUKS2 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 skip the key too. Additionally, enforce some other limits
and fail if needed.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-18 23:00:28 +01:00
Glenn Washburn
278201bc31 luks2: Do not handle disks of size GRUB_DISK_SIZE_UNKNOWN for now
Check to make sure that source disk has a known size. If not, print
a 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-ROM. Since I doubt booting from a LUKS2 volume on
a CD-ROM is a big use case, we'll error until someone complains.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-18 15:19:40 +01:00
Glenn Washburn
90fb18632e luks2: Convert to crypt sectors from GRUB native sectors
The function grub_disk_native_sectors(source) returns the number of sectors
of source in GRUB native (512-byte) sectors, not source sized sectors. So
the conversion needs to use GRUB_DISK_SECTOR_BITS, the GRUB native sector
size.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-18 14:49:56 +01:00
Glenn Washburn
b298eed001 luks2: Error check segment.sector_size
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:05 +01:00
Glenn Washburn
cf3a3acff0 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
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 (i.e. 8 for 4K sectors). Confusingly the IV does not correspond
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
aesthetically pleasing than desired.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:05 +01:00
Glenn Washburn
7ed69b1d1c luks2: grub_cryptodisk_t->total_sectors is the max number of device native 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.

Also, removed an empty statement.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:04 +01:00
Glenn Washburn
40abe8576a luks2: Add string "index" to user strings using a json index
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>
2020-12-12 01:19:04 +01:00
Glenn Washburn
2c7933cd9c luks2: Rename json index variables to names that they are obviously json indexes
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:04 +01:00
Glenn Washburn
64691dddb2 luks2: Use more intuitive object name instead of json index in user messages
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>
2020-12-12 01:19:04 +01:00
Glenn Washburn
1f006c4c05 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 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>
2020-12-12 01:19:04 +01:00
Glenn Washburn
7904c5ce67 luks2: Make sure all fields of output argument in luks2_parse_digest() are written to
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: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:04 +01:00
Glenn Washburn
fe902c3f4c luks2: Remove unused argument in grub_error() call
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:04 +01:00
Glenn Washburn
a06549d398 luks2: Convert 8 spaces to tabs
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:04 +01:00
Glenn Washburn
880dfd8f40 disk: Rename grub_disk_get_size() to grub_disk_native_sectors()
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>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-12-12 01:19:03 +01:00
Glenn Washburn
6213184b26 luks2: Rename index variable "j" to "i" in luks2_get_keyslot()
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>
2020-11-20 15:33:41 +01:00
Glenn Washburn
f36193ddf1 luks2: Rename variable "i" to "keyslot_idx" in luks2_get_keyslot()
Variables named "i" are usually looping variables. So, rename it to
"keyslot_idx" to ease luks2_get_keyslot() reading.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-11-20 15:33:41 +01:00
Glenn Washburn
c28907e235 luks2: Use correct index variable when looping in luks2_get_keyslot()
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>
2020-11-20 15:33:41 +01:00
Glenn Washburn
0eb44d3196 luks2: Rename source disk variable named "disk" to "source" as in luks.c
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>
2020-11-20 15:33:41 +01:00
Glenn Washburn
d78ce33e60 cryptodisk: Rename "offset" in grub_cryptodisk_t to "offset_sectors"
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>
2020-11-20 15:33:41 +01:00
Glenn Washburn
535998c2e0 cryptodisk: Rename "total_length" field in grub_cryptodisk_t to "total_sectors"
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>
2020-11-20 15:33:41 +01:00
Patrick Steinhardt
ee12785f75 luks2: Strip dashes off of the UUID
The UUID header for LUKS2 uses a format with dashes, same as for
LUKS(1). But while we strip these dashes for the latter, we don't for
the former. This isn't wrong per se, but it's definitely inconsistent
for users as they need to use the dashed format for LUKS2 and the
non-dashed format for LUKS when e.g. calling "cryptomount -u $UUID".

Fix this inconsistency by stripping dashes off of the LUKS2 UUID.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-09-18 22:31:29 +02:00
Patrick Steinhardt
eb77486141 luks2: Improve error reporting when decrypting/verifying key
While we already set up error messages in both luks2_verify_key() and
luks2_decrypt_key(), we do not ever print them. This makes it really
hard to discover why a given key actually failed to decrypt a disk.

Improve this by including the error message in the user-visible output.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-09-11 15:48:13 +02:00
Patrick Steinhardt
c543d67810 luks2: Propagate error when reading area key fails
When decrypting a given keyslot, all error cases except for one set up
an error and return the error code. The only exception is when we try to
read the area key: instead of setting up an error message, we directly
print it via grub_dprintf().

Convert the outlier to use grub_error() to allow more uniform handling
of errors.

Signed-off-by: Patrick Steinhardt <ps@kps.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-04-21 22:18:26 +02:00
Patrick Steinhardt
9404c41953 luks2: Add missing newline to debug message
The debug message printed when decryption with a keyslot fails is
missing its trailing newline. Add it to avoid mangling it with
subsequent output.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-02-28 12:27:55 +01:00
Patrick Steinhardt
365e0cc3e7 disk: Implement support for LUKS2
With cryptsetup 2.0, a new version of LUKS was introduced that breaks
compatibility with the previous version due to various reasons. GRUB
currently lacks any support for LUKS2, making it impossible to decrypt
disks encrypted with that version. This commit implements support for
this new format.

Note that LUKS1 and LUKS2 are quite different data formats. While they
do share the same disk signature in the first few bytes, representation
of encryption parameters is completely different between both versions.
While the former version one relied on a single binary header, only,
LUKS2 uses the binary header only in order to locate the actual metadata
which is encoded in JSON. Furthermore, the new data format is a lot more
complex to allow for more flexible setups, like e.g. having multiple
encrypted segments and other features that weren't previously possible.
Because of this, it was decided that it doesn't make sense to keep both
LUKS1 and LUKS2 support in the same module and instead to implement it
in two different modules luks and luks2.

The proposed support for LUKS2 is able to make use of the metadata to
decrypt such disks. Note though that in the current version, only the
PBKDF2 key derival function is supported. This can mostly attributed to
the fact that the libgcrypt library currently has no support for either
Argon2i or Argon2id, which are the remaining KDFs supported by LUKS2. It
wouldn't have been much of a problem to bundle those algorithms with
GRUB itself, but it was decided against that in order to keep down the
number of patches required for initial LUKS2 support. Adding it in the
future would be trivial, given that the code structure is already in
place.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2020-01-10 14:30:24 +01:00