From c2b0e32591e8bcb6358a93318f99698ad62f61c9 Mon Sep 17 00:00:00 2001 From: matt Date: Sat, 8 Apr 2017 08:56:21 -0400 Subject: [PATCH 7/7] Added LUKS patch 3 --- grub-core/disk/luks.c | 258 ++++++++++++++++++++++++++------------------------ 1 file changed, 133 insertions(+), 125 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index a4f2311..c776261 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -445,10 +445,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, static grub_err_t luks_recover_key (grub_disk_t source, - grub_cryptodisk_t dev, - grub_file_t hdr, - grub_uint8_t *keyfile_bytes, - grub_size_t keyfile_bytes_size) + grub_cryptodisk_t dev, + grub_file_t hdr, + grub_uint8_t *keyfile_bytes, + grub_size_t keyfile_bytes_size) { struct grub_luks_phdr header; grub_size_t keysize; @@ -463,6 +463,7 @@ luks_recover_key (grub_disk_t source, grub_size_t max_stripes = 1; char *tmp; grub_uint32_t sector; + unsigned attempts = 2; err = GRUB_ERR_NONE; @@ -485,151 +486,158 @@ luks_recover_key (grub_disk_t source, for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED - && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes) + && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes) max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes); split_key = grub_malloc (keysize * max_stripes); if (!split_key) return grub_errno; - if (keyfile_bytes) + while (attempts) { - /* Use bytestring from key file as passphrase */ - passphrase = keyfile_bytes; - passphrase_length = keyfile_bytes_size; - } - else - { - /* 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 (interactive_passphrase, MAX_PASSPHRASE)) + if (keyfile_bytes) { - grub_free (split_key); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); + /* Use bytestring from key file as passphrase */ + passphrase = keyfile_bytes; + passphrase_length = keyfile_bytes_size; + keyfile_bytes = NULL; /* use it only once */ } + else + { + /* 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 (interactive_passphrase, MAX_PASSPHRASE)) + { + grub_free (split_key); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); + } - passphrase = (grub_uint8_t *)interactive_passphrase; - passphrase_length = grub_strlen (interactive_passphrase); + passphrase = (grub_uint8_t *)interactive_passphrase; + passphrase_length = grub_strlen (interactive_passphrase); - } + } - /* Try to recover master key from each active keyslot. */ - for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) - { - gcry_err_code_t gcry_err; - grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; - grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN]; - - /* Check if keyslot is enabled. */ - if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) - continue; - - 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, - passphrase_length, - header.keyblock[i].passwordSalt, - sizeof (header.keyblock[i].passwordSalt), - grub_be_to_cpu32 (header.keyblock[i]. - passwordIterations), - digest, keysize); - - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + /* Try to recover master key from each active keyslot. */ + for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) + { + gcry_err_code_t gcry_err; + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN]; + + /* Check if keyslot is enabled. */ + if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) + continue; + + 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, + passphrase_length, + header.keyblock[i].passwordSalt, + sizeof (header.keyblock[i].passwordSalt), + grub_be_to_cpu32 (header.keyblock[i]. + passwordIterations), + digest, keysize); + + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - grub_dprintf ("luks", "PBKDF2 done\n"); + grub_dprintf ("luks", "PBKDF2 done\n"); - gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset); - length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes)); + sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset); + length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes)); - /* Read and decrypt the key material from the disk. */ - if (hdr) - { - grub_file_seek (hdr, sector * 512); - if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length) - err = GRUB_ERR_READ_ERROR; - } - else - err = grub_disk_read (source, sector, 0, length, split_key); - if (err) - { - grub_free (split_key); - return err; - } + /* Read and decrypt the key material from the disk. */ + if (hdr) + { + grub_file_seek (hdr, sector * 512); + if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length) + err = GRUB_ERR_READ_ERROR; + } + else + err = grub_disk_read (source, sector, 0, length, split_key); + if (err) + { + grub_free (split_key); + return err; + } - gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0); - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0); + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - /* Merge the decrypted key material to get the candidate master key. */ - gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize, - grub_be_to_cpu32 (header.keyblock[i].stripes)); - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + /* Merge the decrypted key material to get the candidate master key. */ + gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize, + grub_be_to_cpu32 (header.keyblock[i].stripes)); + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - grub_dprintf ("luks", "candidate key recovered\n"); - - /* Calculate the PBKDF2 of the candidate master key. */ - gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key, - grub_be_to_cpu32 (header.keyBytes), - header.mkDigestSalt, - sizeof (header.mkDigestSalt), - grub_be_to_cpu32 - (header.mkDigestIterations), - candidate_digest, - sizeof (candidate_digest)); - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + grub_dprintf ("luks", "candidate key recovered\n"); + + /* Calculate the PBKDF2 of the candidate master key. */ + gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key, + grub_be_to_cpu32 (header.keyBytes), + header.mkDigestSalt, + sizeof (header.mkDigestSalt), + grub_be_to_cpu32 + (header.mkDigestIterations), + candidate_digest, + sizeof (candidate_digest)); + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - /* Compare the calculated PBKDF2 to the digest stored - in the header to see if it's correct. */ - if (grub_memcmp (candidate_digest, header.mkDigest, - sizeof (header.mkDigest)) != 0) - { - grub_dprintf ("luks", "bad digest\n"); - continue; - } + /* Compare the calculated PBKDF2 to the digest stored + in the header to see if it's correct. */ + if (grub_memcmp (candidate_digest, header.mkDigest, + sizeof (header.mkDigest)) != 0) + { + grub_dprintf ("luks", "bad digest\n"); + continue; + } - /* TRANSLATORS: It's a cryptographic key slot: one element of an array - where each element is either empty or holds a key. */ - grub_printf_ (N_("Slot %d opened\n"), i); + /* TRANSLATORS: It's a cryptographic key slot: one element of an array + where each element is either empty or holds a key. */ + grub_printf_ (N_("Slot %d opened\n"), i); - /* Set the master key. */ - gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); - if (gcry_err) - { - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } + /* Set the master key. */ + gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); + if (gcry_err) + { + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } - grub_free (split_key); + grub_free (split_key); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; + } + grub_printf_ (N_("Failed to decrypt master key.\n")); + if (--attempts) grub_printf_ (N_("%u attempt%s remaining.\n"), attempts, + (attempts==1) ? "" : "s"); } grub_free (split_key); -- 2.7.4