From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1maRBB-0005wn-Iq for mharc-grub-devel@gnu.org; Tue, 12 Oct 2021 19:27:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47704) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1maRB9-0005sE-Vy for grub-devel@gnu.org; Tue, 12 Oct 2021 19:27:28 -0400 Received: from mail-qk1-x72d.google.com ([2607:f8b0:4864:20::72d]:37630) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1maRB7-0005Bx-Ph for grub-devel@gnu.org; Tue, 12 Oct 2021 19:27:27 -0400 Received: by mail-qk1-x72d.google.com with SMTP id bl14so630081qkb.4 for ; Tue, 12 Oct 2021 16:27:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=efficientek-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8KSVutfgQmor0bjn7pxAf9q7TbWvP8HCJYd7897xcWg=; b=YiSeVOt/eYKCEpKoGCUAmS+7QtCYX2WPeKN7dm5c+xhiQVrxh57aLwoCOmI40IExj7 RaE7OaIuO596HAtNknAFhqXniDE6cWRZQiMMrMC+zf0J55sGqcOCimvZBQhPtv4LSWzc NbJmGHiQuOrE3/5MbL4ytkZOKdFiUiqUQ5IboM5kR3Y41TIbxFwPmQgCCcYQQduQZgZI EWqTzMB9tuNV3zLzdL1uomxCkrQlMNLYIYuXGVf64JxlffrdOVNSbwDPvp6hB+Qcxwhh vwCS1bw2mfIfOQo4KVNj+QfLf3bNQf1faElmxcWcaMpYkH5GUmeiF6TV4tOohVozBxef 0bvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8KSVutfgQmor0bjn7pxAf9q7TbWvP8HCJYd7897xcWg=; b=6mXujJF+9Pban4PZryf5GfKTGfxdXeON5OBUZKOQuhXg3HFjh6tzkMjgjtQeg4eDkd zGWDtdfKVldfa5B04tFdhZwB7+c9Fdu+raZiEGxTM8TDrwzMtRGZzqukUidKUBxqqk46 dcITohfgqe9jiehrb9SVfkIAOIOYsrfDaM4qexjAJcrslai9+c59oLh1yQrXPHe8Pgc4 qdVuCjox6c+O7bVK7aQRTAZkwbzBKgA63c25DoHAfuZCwtr1dcFcSp3w6I/JBjlB+bWJ ZZUub61BMw89Iaw6d6TIkOk0r8cp/mG0w7WT5Bf5kcW57R785/dDOaa+ES0IR2Rp18Xq iUPw== X-Gm-Message-State: AOAM530+GhcWwEuGihGypQRR17Kv57xMiB91er3fHWq3xo/MAGEe5Bza sP0DWLgU/zIJgWFyHD1f+QqNhg== X-Google-Smtp-Source: ABdhPJzIMHpAbB1rNcIhkezyTwIlAlkqFwZFoNaY4ZO/5Le1+8sgFkWypfWQ0ttmdpGztWCMQevqXg== X-Received: by 2002:a37:4d2:: with SMTP id 201mr16947808qke.97.1634081244900; Tue, 12 Oct 2021 16:27:24 -0700 (PDT) Received: from localhost.localdomain ([37.218.244.251]) by smtp.gmail.com with ESMTPSA id 33sm7121642qtc.18.2021.10.12.16.27.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Oct 2021 16:27:24 -0700 (PDT) From: Glenn Washburn To: Daniel Kiper , grub-devel@gnu.org Cc: Denis 'GNUtoo' Carikli , Patrick Steinhardt , James Bottomley , Glenn Washburn Subject: [PATCH v3 2/4] cryptodisk: Refactor password input out of crypto dev modules into cryptodisk Date: Tue, 12 Oct 2021 18:26:27 -0500 Message-Id: <65a18c5e8b6483833996b9264017c856c90c17a1.1634081029.git.development@efficientek.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=2607:f8b0:4864:20::72d; envelope-from=development@efficientek.com; helo=mail-qk1-x72d.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Oct 2021 23:27:28 -0000 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. Signed-off-by: Glenn Washburn --- grub-core/disk/cryptodisk.c | 52 ++++++++++++++++++++++++++++++------- grub-core/disk/geli.c | 26 ++++--------------- grub-core/disk/luks.c | 27 +++---------------- grub-core/disk/luks2.c | 26 ++++--------------- include/grub/cryptodisk.h | 1 + 5 files changed, 57 insertions(+), 75 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 577942088..a5f7b860c 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,51 @@ grub_cryptodisk_scan_device_real (const char *name, return grub_errno; if (!dev) continue; - - err = cr->recover_key (source, dev, cargs); - if (err) - { - cryptodisk_close (dev); - return err; - } + + if (cargs->key_len == 0) + { + /* Get the passphrase from the user, if no key data. */ + askpass = 1; + 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 ? : "", + dev->uuid); + grub_free (part); + + cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE); + if (!cargs->key_data) + return grub_errno; + + if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE)) + { + ret = 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) + goto error; grub_cryptodisk_insert (dev, name, source); have_it = 1; - return GRUB_ERR_NONE; + goto cleanup; } - return GRUB_ERR_NONE; + goto cleanup; + +error: + cryptodisk_close (dev); +cleanup: + if (askpass) + { + cargs->key_len = 0; + grub_free (cargs->key_data); + } + return ret; } #ifdef GRUB_UTIL diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 4e8c377e7..32f34d5c3 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 || 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 0462edc6e..51646cefe 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 || 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 455a78cb0..c77380cbb 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,8 @@ 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]; + char *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 +555,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 || 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 +583,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 +707,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 +759,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 282f8ac45..5bd970692 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.27.0