grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 2/4] cryptodisk: Refactor password input out of crypto dev


From: Glenn Washburn
Subject: Re: [PATCH v3 2/4] cryptodisk: Refactor password input out of crypto dev modules into cryptodisk
Date: Wed, 1 Dec 2021 15:48:40 -0600

On Wed, 17 Nov 2021 20:10:21 +0100
Daniel Kiper <dkiper@net-space.pl> wrote:

> On Tue, Oct 12, 2021 at 06:26:27PM -0500, Glenn Washburn wrote:
> > 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.
> 
> Mostly nitpicks below...
> 
> > Signed-off-by: Glenn Washburn <development@efficientek.com>
> > ---
> >  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)
> 
> I am OK with "if (!cargs->key_len)" for all kinds of numeric values...
> 
> > +      {
> > +   /* Get the passphrase from the user, if no key data. */
> > +   askpass = 1;
> > +   if (source->partition)
> 
> ...but not for the pointers and enums.
> 
> s/if (source->partition)/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 ? "," : "", part ? : "",
> 
> s/source->partition ? "," : ""/source->partition != NULL ? "," : ""/
> 
> s/part ? : ""/part != NULL ? part : "NO NAME"/?

Ok, when moving code, I generally don't like to change it unless
necesary. I'll add these changes.

> > +                dev->uuid);
> > +   grub_free (part);
> > +
> > +   cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
> > +   if (!cargs->key_data)
> 
> Ditto and below please...
> 
> > +     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");
> 
> All errors printed by grub_error() should start with lower case...

Ok, I'll try to keep that in mind. There's quite a few grub_error()
calls in cryptodisk that do not conform to that (and I expect else
where in the source).

> > +       goto error;
> > +     }
> > +   cargs->key_len = grub_strlen ((char *) cargs->key_data);
> > +      }
> > +
> > +    ret = cr->recover_key (source, dev, cargs);
> > +    if (ret)
> 
> if (ret != GRUB_ERR_NONE)
> 
> > +      goto error;
> >
> >      grub_cryptodisk_insert (dev, name, source);
> >
> >      have_it = 1;
> >
> > -    return GRUB_ERR_NONE;
> > +    goto cleanup;
> >    }
> > -  return GRUB_ERR_NONE;
> > +  goto cleanup;
> > +
> > +error:
> 
> Please put space before labels.

Are you saying you want the line to be " error:"? There are labels in
the source which are preceeded by whitespace, but they seem to be in
the minority. What's the rationale for this? or is it just personal
preference? I don't mind making this change, but I don't understand it.

> 
> > +  cryptodisk_close (dev);
> 
> I would add empty line here.
> 
> > +cleanup:
> 
> Please put space before labels.
> 
> > +  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");
> 
> All errors printed by grub_error() should start with lower case...
> 
> >    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");
> 
> Same as above...
> 
> >    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];
> 
> If you change that could you add a comment why cipher length is equal 32?

I'm not sure why. I think that's a question for Patrick. I'd guess he
figured it was a resonable upper bound on the length of the cipher
string.

> > +  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");
> 
> Same as above...
> 
> Daniel

Glenn




reply via email to

[Prev in Thread] Current Thread [Next in Thread]