forked from pool/grub2
14793c1f96
- Add tpm, tpm2, luks2 and gcry_sha512 to default grub.efi (bsc#1197625) - Make grub-tpm.efi a symlink to grub.efi * grub2.spec - Log error when tpm event log is full and continue * 0001-tpm-Log-EFI_VOLUME_FULL-and-continue.patch - Patch superseded * 0001-tpm-Pass-unknown-error-as-non-fatal-but-debug-print-.patch - Add patches for automatic TPM disk unlock (jsc#SLE-24018) (bsc#1196668) * 0001-luks2-Add-debug-message-to-align-with-luks-and-geli-.patch * 0002-cryptodisk-Refactor-to-discard-have_it-global.patch * 0003-cryptodisk-Return-failure-in-cryptomount-when-no-cry.patch * 0004-cryptodisk-Improve-error-messaging-in-cryptomount-in.patch * 0005-cryptodisk-Improve-cryptomount-u-error-message.patch * 0006-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch * 0007-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch * 0008-cryptodisk-Move-global-variables-into-grub_cryptomou.patch * 0009-cryptodisk-Improve-handling-of-partition-name-in-cry.patch * 0010-protectors-Add-key-protectors-framework.patch * 0011-tpm2-Add-TPM-Software-Stack-TSS.patch * 0012-protectors-Add-TPM2-Key-Protector.patch * 0013-cryptodisk-Support-key-protectors.patch * 0014-util-grub-protect-Add-new-tool.patch - Fix no disk unlocking happen (bsc#1196668) * 0001-crytodisk-fix-cryptodisk-module-looking-up.patch - Fix build error * fix-tpm2-build.patch OBS-URL: https://build.opensuse.org/request/show/992180 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=417
343 lines
12 KiB
Diff
343 lines
12 KiB
Diff
From a3ae3f800f6aa3f6036351133ed69fa47c9fa371 Mon Sep 17 00:00:00 2001
|
|
From: Glenn Washburn <development@efficientek.com>
|
|
Date: Thu, 9 Dec 2021 11:14:56 -0600
|
|
Subject: [PATCH 07/14] 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 f4794fddac..4504bcabec 100644
|
|
--- a/docs/grub.texi
|
|
+++ b/docs/grub.texi
|
|
@@ -4310,9 +4310,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 14c661a86e..d12368a1f7 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 777da3a055..7299a47d19 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 c5858fcf8a..39a7af6a43 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 2cbec8acc2..09740b53f9 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,
|
|
@@ -549,8 +547,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;
|
|
@@ -560,9 +557,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)
|
|
@@ -589,18 +585,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))
|
|
{
|
|
@@ -725,7 +709,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",
|
|
@@ -777,7 +761,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 282f8ac456..5bd970692f 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;
|
|
|
|
--
|
|
2.34.1
|
|
|