grub2/0383-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
Nicolas Frayer 6eaa34fe07 Add several CVE fixes
- Resolves: CVE-2024-45779 CVE-2024-45778 CVE-2025-1118
- Resolves: CVE-2025-0677 CVE-2024-45782 CVE-2025-0690
- Resolves: CVE-2024-45783 CVE-2025-0624 CVE-2024-45776
- Resolves: CVE-2025-0622 CVE-2024-45774 CVE-2024-45775
- Resolves: CVE-2024-45781 CVE-2024-45780
- Resolves: #RHEL-79700
- Resolves: #RHEL-79341
- Resolves: #RHEL-79875
- Resolves: #RHEL-79849
- Resolves: #RHEL-79707
- Resolves: #RHEL-79857
- Resolves: #RHEL-79709
- Resolves: #RHEL-79846
- Resolves: #RHEL-75737
- Resolves: #RHEL-79713
- Resolves: #RHEL-73785
- Resolves: #RHEL-73787
- Resolves: #RHEL-79704
- Resolves: #RHEL-79702

Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
2025-02-18 19:06:15 +01:00

340 lines
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:56 -0600
Subject: [PATCH] cryptodisk: Refactor password input out of crypto dev modules
into cryptodisk
The crypto device modules should only be setting up the crypto devices and
not getting user input. This has the added benefit of simplifying the code
such that three essentially duplicate pieces of code are merged into one.
Add documentation of passphrase option for cryptomount as it is now usable.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 8 ++++---
grub-core/disk/cryptodisk.c | 56 ++++++++++++++++++++++++++++++++++++---------
grub-core/disk/geli.c | 26 ++++-----------------
grub-core/disk/luks.c | 27 ++++------------------
grub-core/disk/luks2.c | 25 ++++----------------
include/grub/cryptodisk.h | 1 +
6 files changed, 64 insertions(+), 79 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index b39cdf2..3c7d99e 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4329,9 +4329,11 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
@node cryptomount
@subsection cryptomount
-@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
-Setup access to encrypted device. If necessary, passphrase
-is requested interactively. Option @var{device} configures specific grub device
+@deffn Command cryptomount [@option{-p} password] device|@option{-u} uuid|@option{-a}|@option{-b}
+Setup access to encrypted device. If @option{-p} is not given, a passphrase
+is requested interactively. Otherwise, the given @var{password} will be used and
+no passphrase will be requested interactively.
+Option @var{device} configures specific grub device
(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
with specified @var{uuid}; option @option{-a} configures all detected encrypted
devices; option @option{-b} configures all geli containers that have boot flag set.
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 14c661a..d12368a 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1001,9 +1001,11 @@ grub_cryptodisk_scan_device_real (const char *name,
grub_disk_t source,
grub_cryptomount_args_t cargs)
{
- grub_err_t err;
+ grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
+ int askpass = 0;
+ char *part = NULL;
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -1017,21 +1019,53 @@ grub_cryptodisk_scan_device_real (const char *name,
return NULL;
if (!dev)
continue;
-
- err = cr->recover_key (source, dev, cargs);
- if (err)
- {
- cryptodisk_close (dev);
- return NULL;
- }
+
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ if (source->partition != NULL)
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : "",
+ dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ return NULL;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
grub_cryptodisk_insert (dev, name, source);
- return dev;
+ goto cleanup;
}
-
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
- return NULL;
+ goto cleanup;
+
+ error:
+ cryptodisk_close (dev);
+ dev = NULL;
+
+ cleanup:
+ if (askpass)
+ {
+ cargs->key_len = 0;
+ grub_free (cargs->key_data);
+ }
+ return dev;
}
#ifdef GRUB_UTIL
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 777da3a..7299a47 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -135,8 +135,6 @@ const char *algorithms[] = {
[0x16] = "aes"
};
-#define MAX_PASSPHRASE 256
-
static gcry_err_code_t
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
{
@@ -406,17 +404,14 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
grub_uint8_t geli_cipher_key[64];
- char passphrase[MAX_PASSPHRASE] = "";
unsigned i;
gcry_err_code_t gcry_err;
struct grub_geli_phdr header;
- char *tmp;
grub_disk_addr_t sector;
grub_err_t err;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
@@ -438,23 +433,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_puts_ (N_("Attempting to decrypt master key..."));
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
-
/* Calculate the PBKDF2 of the user supplied passphrase. */
if (grub_le_to_cpu32 (header.niter) != 0)
{
grub_uint8_t pbkdf_key[64];
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.salt,
sizeof (header.salt),
grub_le_to_cpu32 (header.niter),
@@ -477,7 +461,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
- grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
+ grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
if (gcry_err)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index c5858fc..39a7af6 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -29,8 +29,6 @@
GRUB_MOD_LICENSE ("GPLv3+");
-#define MAX_PASSPHRASE 256
-
#define LUKS_KEY_ENABLED 0x00AC71F3
/* On disk LUKS header */
@@ -158,17 +156,14 @@ luks_recover_key (grub_disk_t source,
struct grub_luks_phdr header;
grub_size_t keysize;
grub_uint8_t *split_key = NULL;
- char passphrase[MAX_PASSPHRASE] = "";
grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
unsigned i;
grub_size_t length;
grub_err_t err;
grub_size_t max_stripes = 1;
- char *tmp;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
@@ -188,20 +183,6 @@ luks_recover_key (grub_disk_t source,
if (!split_key)
return grub_errno;
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- {
- grub_free (split_key);
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
- }
-
/* Try to recover master key from each active keyslot. */
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
{
@@ -216,8 +197,8 @@ luks_recover_key (grub_disk_t source,
grub_dprintf ("luks", "Trying keyslot %d\n", i);
/* Calculate the PBKDF2 of the user supplied passphrase. */
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.keyblock[i].passwordSalt,
sizeof (header.keyblock[i].passwordSalt),
grub_be_to_cpu32 (header.keyblock[i].
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 8a9f42d..0425100 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -35,8 +35,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define LUKS_MAGIC_1ST "LUKS\xBA\xBE"
#define LUKS_MAGIC_2ND "SKUL\xBA\xBE"
-#define MAX_PASSPHRASE 256
-
enum grub_luks2_kdf_type
{
LUKS2_KDF_TYPE_ARGON2I,
@@ -546,8 +544,7 @@ luks2_recover_key (grub_disk_t source,
grub_cryptomount_args_t cargs)
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
- char passphrase[MAX_PASSPHRASE], cipher[32];
- char *json_header = NULL, *part = NULL, *ptr;
+ char cipher[32], *json_header = NULL, *ptr;
grub_size_t candidate_key_len = 0, json_idx, size;
grub_luks2_header_t header;
grub_luks2_keyslot_t keyslot;
@@ -557,9 +554,8 @@ luks2_recover_key (grub_disk_t source,
grub_json_t *json = NULL, keyslots;
grub_err_t ret;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
ret = luks2_read_header (source, &header);
if (ret)
@@ -586,18 +582,6 @@ luks2_recover_key (grub_disk_t source,
goto err;
}
- /* Get the passphrase from the user. */
- 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))
- {
- ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
- goto err;
- }
-
if (grub_json_getvalue (&keyslots, json, "keyslots") ||
grub_json_getsize (&size, &keyslots))
{
@@ -722,7 +706,7 @@ luks2_recover_key (grub_disk_t source,
}
ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
- (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
+ cargs->key_data, cargs->key_len);
if (ret)
{
grub_dprintf ("luks2", "Decryption with keyslot \"%" PRIuGRUB_UINT64_T "\" failed: %s\n",
@@ -774,7 +758,6 @@ luks2_recover_key (grub_disk_t source,
}
err:
- grub_free (part);
grub_free (json_header);
grub_json_free (json);
return ret;
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 282f8ac..5bd9706 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -59,6 +59,7 @@ typedef enum
#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
struct grub_cryptodisk;