return newdev;
}
+static gcry_err_code_t
+luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize)
+{
+ gcry_err_code_t err;
+ int real_keysize;
+
+ real_keysize = keysize;
+ if (dev->mode == GRUB_LUKS_MODE_XTS)
+ real_keysize /= 2;
+ if (dev->mode == GRUB_LUKS_MODE_LRW)
+ real_keysize -= dev->cipher->cipher->blocksize;
+
+ /* Set the PBKDF2 output as the cipher key. */
+ err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize);
+ if (err)
+ return err;
+
+ /* Configure ESSIV if necessary. */
+ if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV)
+ {
+ grub_size_t essiv_keysize = dev->essiv_hash->mdlen;
+ grub_uint8_t hashed_key[essiv_keysize];
+
+ grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize);
+ err = grub_crypto_cipher_set_key (dev->essiv_cipher,
+ hashed_key, essiv_keysize);
+ if (err)
+ return err;
+ }
+ if (dev->mode == GRUB_LUKS_MODE_XTS)
+ {
+ err = grub_crypto_cipher_set_key (dev->secondary_cipher,
+ key + real_keysize,
+ keysize / 2);
+ if (err)
+ return err;
+ }
+
+ if (dev->mode == GRUB_LUKS_MODE_LRW)
+ grub_memcpy (dev->lrw_key, key + real_keysize,
+ dev->cipher->cipher->blocksize);
+ return GPG_ERR_NO_ERROR;
+}
+
static grub_err_t
luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header,
const char *name, grub_disk_t source)
grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes);
grub_uint8_t candidate_key[keysize];
grub_uint8_t digest[keysize];
- grub_uint8_t *hashed_key = NULL;
grub_uint8_t *split_key = NULL;
char passphrase[MAX_PASSPHRASE] = "";
grub_uint8_t candidate_digest[sizeof (header->mkDigest)];
unsigned i;
- grub_size_t essiv_keysize = 0;
grub_size_t length;
grub_err_t err;
- if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV)
- {
- essiv_keysize = dev->essiv_hash->mdlen;
- hashed_key = grub_malloc (dev->essiv_hash->mdlen);
- if (!hashed_key)
- return grub_errno;
- }
-
grub_printf ("Attempting to decrypt master key...\n");
split_key = grub_malloc (keysize * LUKS_STRIPES);
if (!split_key)
- {
- grub_free (hashed_key);
- return grub_errno;
- }
+ return grub_errno;
/* Get the passphrase from the user. */
grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid);
if (!grub_password_get (passphrase, MAX_PASSPHRASE))
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
}
for (i = 0; i < ARRAY_SIZE (header->keyblock); i++)
{
gcry_err_code_t gcry_err;
- int real_keysize;
/* Check if keyslot is enabled. */
if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED)
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_dprintf ("luks", "PBKDF2 done\n");
- real_keysize = keysize;
- if (dev->mode == GRUB_LUKS_MODE_XTS)
- real_keysize /= 2;
- if (dev->mode == GRUB_LUKS_MODE_LRW)
- real_keysize -= dev->cipher->cipher->blocksize;
-
- /* Set the PBKDF2 output as the cipher key. */
- gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, real_keysize);
+ gcry_err = luks_setkey (dev, digest, keysize);
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
- /* Configure ESSIV if necessary. */
- if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV)
- {
- grub_crypto_hash (dev->essiv_hash, hashed_key, digest, keysize);
- gcry_err = grub_crypto_cipher_set_key (dev->essiv_cipher,
- hashed_key,
- essiv_keysize);
- if (gcry_err)
- {
- grub_free (hashed_key);
- grub_free (split_key);
- return grub_crypto_gcry_error (gcry_err);
- }
- }
-
- if (dev->mode == GRUB_LUKS_MODE_XTS)
- {
- gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher,
- digest + real_keysize,
- keysize / 2);
- if (gcry_err)
- {
- grub_free (hashed_key);
- grub_free (split_key);
- return grub_crypto_gcry_error (gcry_err);
- }
- }
-
- if (dev->mode == GRUB_LUKS_MODE_LRW)
- grub_memcpy (dev->lrw_key, digest + real_keysize,
- dev->cipher->cipher->blocksize);
-
- length =
- grub_be_to_cpu32 (header->keyBytes) *
- grub_be_to_cpu32 (header->keyblock[i].stripes);
+ length = (grub_be_to_cpu32 (header->keyBytes)
+ * grub_be_to_cpu32 (header->keyblock[i].stripes));
/* Read and decrypt the key material from the disk. */
err = grub_disk_read (source,
length, split_key);
if (err)
{
- grub_free (hashed_key);
grub_free (split_key);
return err;
}
gcry_err = luks_decrypt (dev, split_key, length, 0);
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_be_to_cpu32 (header->keyblock[i].stripes));
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
sizeof (candidate_digest));
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_printf ("Slot %d opened\n", i);
/* Set the master key. */
- gcry_err = grub_crypto_cipher_set_key (dev->cipher, candidate_key,
- real_keysize);
+ gcry_err = luks_setkey (dev, candidate_key, keysize);
if (gcry_err)
{
- grub_free (hashed_key);
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
- /* Configure ESSIV if necessary. */
- if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV)
- {
- grub_crypto_hash (dev->essiv_hash, hashed_key,
- candidate_key, keysize);
- gcry_err =
- grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key,
- essiv_keysize);
- if (gcry_err)
- {
- grub_free (hashed_key);
- grub_free (split_key);
- return grub_crypto_gcry_error (gcry_err);
- }
- }
-
- if (dev->mode == GRUB_LUKS_MODE_XTS)
- {
- gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher,
- candidate_key + real_keysize,
- keysize / 2);
- if (gcry_err)
- {
- grub_free (hashed_key);
- grub_free (split_key);
- return grub_crypto_gcry_error (gcry_err);
- }
- }
-
- if (dev->mode == GRUB_LUKS_MODE_LRW)
- grub_memcpy (dev->lrw_key, candidate_key + real_keysize,
- dev->cipher->cipher->blocksize);
-
grub_free (split_key);
- grub_free (hashed_key);
return GRUB_ERR_NONE;
}