The --hw-accel option has been added to cryptomount to speed up
decryption by temporarily enabling hardware-specific instruction
sets (e.g., AVX, SSE) in libgcrypt.
A new feature, "feature_gcry_hw_accel", is also introduced to mark the
availability of the new option.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
To enable more efficient buffer reuse for HMAC operations three new
functions have been introduced. This change prevents the need to
reallocate memory for each HMAC operation:
- grub_crypto_hmac_reset(): reinitializes the hash contexts in the HMAC handle,
- grub_crypto_hmac_final(): provides the final HMAC result without freeing the
handle allowing it to be reused immediately,
- grub_crypto_hmac_free(): deallocates the HMAC handle and its associated memory.
To further facilitate buffer reuse ctx2 is now included within the HMAC handle
struct and the initialization of ctx2 is moved to grub_crypto_hmac_init().
The intermediate hash states, ctx and ctx2, for the inner and outer padded
keys are now cached. The grub_crypto_hmac_reset() restores these cached
states for new operations which avoids redundant hashing of the keys.
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Leverage the new grub_crypto_argon2() function to add support for the
Argon2i and Argon2id KDFs in LUKS2.
Signed-off-by: Gary Lin <glin@suse.com>
Tested-By: Waldemar Brodkorb <wbx@openadk.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This patches modifies the GRUB-libgcrypt API to match new libgcrypt 1.11.
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The option can be used to suppress output if we only want to test the
return value of the command.
Also, mention this option in the documentation.
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Switching to another EFI boot application while there are secrets in
RAM is dangerous, because not all firmware is wiping memory on free.
To reduce the attack surface, wipe the passphrase acquired when
unlocking an encrypted volume.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit adds the grub_cryptodisk_erasesecrets() function to wipe
master keys from all cryptodisks. This function is EFI-only.
Since there is no easy way to "force unmount" a given encrypted disk,
this function renders all mounted cryptodisks unusable. An attempt to
read them will return garbage.
This is why this function must be used in "no way back" conditions.
Currently, it is used when unloading the cryptodisk module and when
performing the "exit" command (it is often used to switch to the next
EFI application). This function is not called when performing the
"chainloader" command, because the callee may return to GRUB. For this
reason, users are encouraged to use "exit" instead of "chainloader" to
execute third-party boot applications.
This function does not guarantee that all secrets are wiped from RAM.
Console output, chunks from disk read requests and other may remain.
This function does not clear the IV prefix and rekey key for geli disks.
Also, this commit adds the relevant documentation improvements.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This command examines a given diskfilter device, e.g., an LVM disk,
and checks if underlying disks, physical volumes, are cryptodisks,
e.g., LUKS disks, this layout is called "LVM-on-LUKS".
The return value is 0 when all underlying disks (of a given device)
are cryptodisks (1 if at least one disk is unencrypted or in an
unknown state).
Users are encouraged to include the relevant check before loading
anything from an LVM disk that is supposed to be encrypted.
This further supports the CLI authentication, blocking bypass
attempts when booting from an encrypted LVM disk.
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Fix memory leaks in make_vg() with new helper functions, free_pv()
and free_lv(). Additionally, correct a check after allocating
comp->segments->nodes that mistakenly checked lv->segments->nodes
instead, likely due to a copy-paste error.
Fixes: CID 473878
Fixes: CID 473884
Fixes: CID 473889
Fixes: CID 473890
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Mark cachevol LV's as ignored features, which is true only if they are
configured as "writethrough". This patch does not let GRUB boot from
"writeback" cache-enabled LV's.
Signed-off-by: Patrick Plenefisch <simonpatp@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The LV matching must be done after processing the ignored feature
indirections, as integrity volumes & caches may have several levels
of indirection that the segments must be shifted through.
Signed-off-by: Patrick Plenefisch <simonpatp@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The PV matching must be completely finished before validating a volume,
otherwise referenced RAID stripes may not have PV data applied yet.
This change is required for integrity & cachevol support.
Signed-off-by: Patrick Plenefisch <simonpatp@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The cache_pool is never read or used, remove it.
Signed-off-by: Patrick Plenefisch <simonpatp@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This patch isn't necessary by itself, but when combined with subsequent
patches it enhances readability as ignored_features_lv is then used for
multiple types of extra LV's, not just cache LV's.
Signed-off-by: Patrick Plenefisch <simonpatp@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The conditional makes no sense when the two possible expressions have
the same value, so, remove it (perhaps the compiler does it for us but
better to remove it). This change makes spinup argument unused. So, drop
it as well.
Signed-off-by: Leo Sandoval <lsandova@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
In the dev_iterate() function a handle is opened but isn't closed when
grub_malloc() returns NULL. We should fix this by closing it on error.
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
When using grub_malloc(), grub_zalloc() or grub_calloc(), these functions can
fail if we are out of memory. After allocating memory we should check if these
functions returned NULL and handle this error if they did.
On the occasion make a NULL check in ATA code more obvious.
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Use grub_calloc() when allocating memory for arrays to ensure proper
overflow checks are in place.
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Replace direct arithmetic operations with macros from include/grub/safemath.h
to prevent potential overflow issues when calculating the memory sizes.
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
It was possible to delete a loopback while there were still references
to it. This led to an exploitable use-after-free.
Fixed by implementing a reference counting in the grub_loopback struct.
Reported-by: B Horn <b@horn.uk>
Signed-off-by: B Horn <b@horn.uk>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The GRUB may use TPM to verify the integrity of boot components and the
result can determine whether a previously sealed key can be released. If
everything checks out, showing nothing has been tampered with, the key
is released and GRUB unlocks the encrypted root partition for the next
stage of booting.
However, the liberal Command Line Interface (CLI) can be misused by
anyone in this case to access files in the encrypted partition one way
or another. Despite efforts to keep the CLI secure by preventing utility
command output from leaking file content, many techniques in the wild
could still be used to exploit the CLI, enabling attacks or learning
methods to attack. It's nearly impossible to account for all scenarios
where a hack could be applied.
Therefore, to mitigate potential misuse of the CLI after the root device
has been successfully unlocked via TPM, the user should be required to
authenticate using the LUKS password. This added layer of security
ensures that only authorized users can access the CLI reducing the risk
of exploitation or unauthorized access to the encrypted partition.
Fixes: CVE-2024-49504
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
When using disk auto-unlocking with TPM 2.0, the typical grub.cfg may
look like this:
tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub/sealed.tpm
cryptomount -u <PART-UUID> -P tpm2
search --fs-uuid --set=root <FS-UUID>
Since the disk search order is based on the order of module loading, the
attacker could insert a malicious disk with the same FS-UUID root to
trick GRUB to boot into the malicious root and further dump memory to
steal the unsealed key.
Do defend against such an attack, we can specify the hint provided by
"grub-probe" to search the encrypted partition first:
search --fs-uuid --set=root --hint='cryptouuid/<PART-UUID>' <FS-UUID>
However, for LVM on an encrypted partition, the search hint provided by
"grub-probe" is:
--hint='lvmid/<VG-UUID>/<LV-UUID>'
It doesn't guarantee to look up the logical volume from the encrypted
partition, so the attacker may have the chance to fool GRUB to boot
into the malicious disk.
To minimize the attack surface, this commit tweaks the disk device search
in diskfilter to look up cryptodisk devices first and then others, so
that the auto-unlocked disk will be found first, not the attacker's disk.
Cc: Fabian Vogt <fvogt@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
An attacker may insert a malicious disk with the same crypto UUID and
trick GRUB to mount the fake root. Even though the key from the key
protector fails to unlock the fake root, it's not wiped out cleanly so
the attacker could dump the memory to retrieve the secret key. To defend
such attack, wipe out the cached key when we don't need it.
Cc: Fabian Vogt <fvogt@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
If a protector is specified, but it fails to unlock the disk, fall back
to asking for the passphrase.
Before requesting the passphrase, the error from the key protector(s)
has to be cleared, or the later code, e.g., LUKS code, may stop as
grub_errno is set. This commit prints error from the key protector(s)
and sets grub_errno to GRUB_ERR_NONE to have a fresh start.
Signed-off-by: Patrick Colp <patrick.colp@oracle.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Add a new parameter to cryptomount to support the key protectors framework: -P.
The parameter is used to automatically retrieve a key from specified key
protectors. The parameter may be repeated to specify any number of key
protectors. These are tried in order until one provides a usable key for any
given disk.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Michael Chang <mchang@suse.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
A key protector encapsulates functionality to retrieve an unlocking key
for a fully-encrypted disk from a specific source. A key protector
module registers itself with the key protectors framework when it is
loaded and unregisters when unloaded. Additionally, a key protector may
accept parameters that describe how it should operate.
The key protectors framework, besides offering registration and
unregistration functions, also offers a one-stop routine for finding and
invoking a key protector by name. If a key protector with the specified
name exists and if an unlocking key is successfully retrieved by it, the
function returns to the caller the retrieved key and its length.
Cc: Vladimir Serbinenko <phcoder@gmail.com>
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
Signed-off-by: Gary Lin <glin@suse.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
When handling a regular LVM volume, GRUB can fail with the message:
error: disk `lvmid/******-****-****-****-****-****-****/******-****-****-****-****-****-******' not found.
If the condition which triggers this exists, grub-probe will report the
error mentioned above. Similarly, the GRUB boot code will fail to detect
LVM volumes, resulting in a failure to boot off of LVM disks/partitions.
The condition can be created on any LVM VG by an LVM configuration change,
so any system with /boot on LVM can become unbootable at "any" time (after
any LVM configuration change).
The problem is caused by an incorrect computation of mda_end in disk/lvm.c,
when the metadata area wraps around. Apparently, this can start happening at
around 220 metadata changes to the VG.
Fixes: 879c4a834 (lvm: Fix two more potential data-dependent alloc overflows)
Fixes: https://savannah.gnu.org/bugs/?61620
Signed-off-by: Rogier <rogier777@gmail.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-By: Michael Chang <mchang@suse.com>
Give the user a chance to re-enter their cryptodisk passphrase after a typo,
rather than immediately failing (and likely dumping them into a GRUB shell).
By default, we allow 3 tries before giving up. A value in the
cryptodisk_passphrase_tries environment variable will override this default.
The user can give up early by entering an empty passphrase, just as they
could before this patch.
Signed-off-by: Forest <forestix@nom.one>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The test corpus for version-1 RAID generated an infinite recursion
in grub_partition_iterate() while attempting to read the superblock.
The reason for the issue was that the data region overlapped with
the superblock.
The infinite call loop looks like this:
grub_partition_iterate() -> partmap->iterate() ->
-> grub_disk_read() -> grub_disk_read_small() ->
-> grub_disk_read_small_real() -> grub_diskfilter_read() ->
-> read_lv() -> read_segment() -> grub_diskfilter_read_node() ->
-> grub_disk_read() -> grub_disk_read_small() -> ...
The fix adds checks for both the superblock region and the data
region when parsing the superblock metadata in grub_mdraid_detect().
Signed-off-by: Lidong Chen <lidong.chen@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Variable e is set but never used. We can just remove it now.
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Current code imposes limitations on the amount of sectors read in
a single call according to CHS layout of the disk even in LBA
read mode. There's no need to obey CHS layout restrictions for
LBA reads on LBA disks. It only slows down booting process.
See: https://lore.kernel.org/grub-devel/d42a11fa-2a59-b5e7-08b1-d2c60444bb99@valdikss.org.ru/
Signed-off-by: ValdikSS <iam@valdikss.org.ru>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
The sector size in bytes is added to each line and it is allowed to be
6 decimal digits long, which covers the most common cases of 512 and 4096
byte sectors with space for two additional digits as future-proofing. The
size allocation is updated to reflect this additional field. Also make
clearer the size allocation calculation.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Use the return value of grub_snprintf() to move the string pointer forward,
instead of incrementing the string pointer iteratively until a NULL byte is
reached. Move the space out of the format string argument, a small
optimization, but also makes the spacing clearer. Also, use the new
PRIxGRUB_OFFSET instead of PRIuGRUB_UINT64_T to accurately reflect the
format string for this type.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This was causing the cryptomount command to return failure even though
the crypto device was successfully added. Of course, this meant that any
script using the return code would behave unexpectedly.
Fixes: 3cf2e848bc03 (disk/cryptodisk: Allows UUIDs to be compared in a dash-insensitive manner)
Suggested-by: Olaf Hering <olaf@aepfle.de>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrich Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Move the constant from grub-core/osdep/linux/getroot.c to
include/grub/disk.h and then reuse it in place of the
hardcoded 1024 limit in diskfilter.
Fixes: 2a5e3c1f2 (disk/diskfilter: Don't make a RAID array with more than 1024 disks)
Cc: Daniel Axtens <dja@axtens.net>
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
There are 3 implementations of a GUID in GRUB. Replace them with
a common one, placed in types.h.
It uses the "packed" flavor of the GUID structs, the alignment attribute
is dropped, since it is not required.
Signed-off-by: Oliver Steffen <osteffen@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Now that GCC can generate function calls using the correct calling
convention for us, we can stop using the efi_call_XX() wrappers, and
just dereference the function pointers directly.
This avoids the untyped variadic wrapper routines, which means better
type checking for the method calls.
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
When using grub-probe with cryptodisk, the mapped block device from the host
is used directly instead of decrypting the source device in GRUB code.
In that case, the sector size and count of the host device needs to be used.
This is especially important when using LUKS2, which does not assign
total_sectors and log_sector_size when scanning, but only later when the
segments in the JSON area are evaluated. With an unset log_sector_size,
grub_device_open() complains.
This fixes grub-probe failing with
"error: sector sizes of 1 bytes aren't supported yet.".
Signed-off-by: Fabian Vogt <fvogt@suse.de>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Tested-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This patch adds support for plain encryption mode, plain dm-crypt, via
new module/command named "plainmount".
Signed-off-by: Maxim Fomin <maxim@fomin.one>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Glenn Washburn <development@efficientek.com>
This is "belt and braces" with commit 12e20a6a695f (disk/diskfilter:
Check calloc() result for NULL): we end up trying to use too much memory
in situations like corrupted Linux software RAID setups purporting to
use a huge number of disks. Simply refuse to permit such configurations.
1024 is a bit arbitrary, yes, and I feel a bit like I'm tempting fate
here, but I think 1024 disks in an array (that GRUB has to read to boot!)
should be enough for anyone.
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
In the function grub_cryptodisk_endecrypt(), a for loop is incrementing the
variable i by (1U << log_sector_size). The variable i is of type grub_size_t
which is a 64-bit unsigned integer on x86_64 architecture. On the other hand, 1U
is a 32-bit unsigned integer. By performing a left shift on a 32-bit value and
assigning it to a 64-bit variable, the 64-bit variable may have incorrect values
in the high 32-bits if the shift has an overflow. To avoid this, we replace 1U
with (grub_size_t)1.
Fixes: CID 307788
Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
With wildly corrupt inputs, we can end up trying to calloc a very
large amount of memory, which will fail and give us a NULL pointer.
We need to check that to avoid a crash. (And, even if we blocked
such inputs, it is good practice to check the results of allocations
anyway.)
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
A user can now specify UUID strings with dashes, instead of having to remove
dashes. This is backwards-compatibility preserving and also fixes a source
of user confusion over the inconsistency with how UUIDs are specified
between file system UUIDs and cryptomount UUIDs. Since cryptsetup, the
reference implementation for LUKS, displays and generates UUIDs with dashes
there has been additional confusion when using the UUID strings from
cryptsetup as exact input into GRUB does not find the expected cryptodisk.
A new function grub_uuidcasecmp() is added that is general enough to be used
other places where UUIDs are being compared.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
A new option is added to the loopback command, -D or --decompress, which
when specified transparently decompresses the backing file. This allows
compressed images to be used as if they were uncompressed.
Add documentation to support this change.
Suggested-by: Li Gen <ligenlive@gmail.com>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
It was reported in the #grub IRC channel on Libera that decryption of
LUKS2 partitions fails with errors about invalid digests and/or salts.
In all of these cases, what failed was decoding the Base64
representation of these, where the encoded data contained invalid
characters.
As it turns out, the root cause is that json-c, which is used by
cryptsetup to read and write the JSON header, will escape some
characters by prepending a backslash when writing JSON strings by
default. Most importantly, json-c also escapes the forward slash, which
is part of the Base64 alphabet. Because GRUB doesn't know to unescape
such characters, decoding this string will rightfully fail.
Interestingly, this issue has until now only been reported by users of
Ubuntu 18.04. And a bit of digging in fact reveals that cryptsetup has
changed the logic in a054206d (Suppress useless slash escaping in json
lib, 2018-04-20), which has been released with cryptsetup v2.0.3. Ubuntu
18.04 is still shipping with cryptsetup v2.0.2 though, which explains
why this is not a more frequent issue.
Fix the issue by using our new grub_json_unescape() helper function
that handles unescaping for us.
Reported-by: Afdal
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Reviewed-by: Daniel Kiper <dkiper@net-space.pl>
Update the read hook to take into account encrypted volumes on a partition.
GRUB disk read hooks supply an absolute sector number at which the read is
started from. If the encrypted volume is in a partition, the sector number
given to the read hook will be offset by the number of the sector at the
start of the partition. The read hook then needs to subtract the partition
start from the supplied sector to get the correct start sector for the read
into the detached header file.
Reported-by: brutser <brutser@perso.be>
Signed-off-by: Glenn Washburn <development@efficientek.com>
Tested-by: brutser <brutser@perso.be>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>