grub-devel
[Top][All Lists]
Advanced

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

Re: [PATCH] Cryptomount support for key files and detached header


From: Glenn Washburn
Subject: Re: [PATCH] Cryptomount support for key files and detached header
Date: Tue, 10 Nov 2020 14:25:07 -0600

On Tue, 10 Nov 2020 01:09:20 +0300
Dmitry <reagentoo@gmail.com> wrote:

> вт, 10 нояб. 2020 г. в 00:34, Glenn Washburn
> <development@efficientek.com>:
> >
> > On Mon, 9 Nov 2020 10:56:51 +0300
> > Dmitry <reagentoo@gmail.com> wrote:
> >
> > > Thanks for feedback. First of all I think it's preferable to
> > > introduce the master-key option at the beginning. Because I see
> > > no point for a user to use a standard slot key along with a
> > > detached header. Decryption from key to master key takes a long
> > > time. (30 seconds for argon2i).
> >
> > Are you using the argon patches on this list, which haven't been
> > committed to run that test?  Because currently there is no support
> > for Argon2.
> 
> I'm using argon2 patchset from Patrick Steinhardt:
> https://lists.gnu.org/archive/html/grub-devel/2020-02/msg00040.html
> More info:
> https://github.com/johnlane/grub/issues/21#issuecomment-721097980
> 
> >
> > Second detached headers have nothing to do with how long Argon2 or
> > any other key derivation function takes to complete, so they are
> > independent (or am I wrong?).  Am I correct in understanding you to
> > say that argon2i is faster without having a detached header?
> 
> No. I talked about usage pattern.
> It makes no sense to use a detached header and a keyfile that are
> stored on the same device. 

I take you to mean that it makes no sense because using a master key is
more efficient.  And I agree.

> And therefore it is better to use a
> master-key that doesn't need to be decrypted with the argon2 algorithm
> (or old LUKS2_KDF_TYPE_PBKDF2 method).

It does not follow that _in general_ the master key feature is more
useful than detached header support.  Perhaps I misunderstood what
you were initially suggesting.  And on the contrary, I would say that
detached header support is more important because the master key
feature is only an efficiency enhancement, while detached header is a
functional enhancement.  So I still think the preferred path forward is
to merge the previous detached header support, then add the master key
on top.

> In this case we need a header file only for master-key verification.
> (digest comparison in luks2_verify_key).
>
> >
> > Third, I actually do currently use detached headers (as I said
> > before I have an unsubmitted patch which adds detached header and
> > keyfile). And separately, yes the key derivation can take a while
> > (compared to running in linux). I'm not exactly clear on why this
> > is. I have some ideas, like the code grub is using to do crypto or
> > grub's runtime environment, but I haven't really looked in to it.
> > Do you have any ideas?  And I know there are others currently using
> > the detached header without the master key option, so there's
> > definitely a point.
> >
> The mailing lists have suggested that SSE instructions should be used
> to speed up decryption:
> https://lists.gnu.org/archive/html/grub-devel/2018-01/msg00026.html

Good find.  This should be a good starting point.

> > > Regarding keyfile-offset and keyfile-size options I suggest to
> > > introduce this options in separate patches. Yes, maybe you
> > > variant to pass the pointer and size
> > > (correct me if I am wrong) to luks2_recover_key is better of
> > > files. But then you need to think in advance how to add
> > > master-key option.
> >
> > It can be added just like the key-file option was added in the
> > previous patch series.  Read the master key file from
> > grub_cmd_cryptomount.
> >

Also, I forgot to mention that I think any new features accepted to
grub should have accompanying documentation changes.  The previous
detached header patches don't either, but I think this should be
essentially required.

Glenn

> >
> > > пн, 9 нояб. 2020 г. в 06:16, Glenn Washburn
> > > <development@efficientek.com>:
> > >
> > > > I've read through the patch but not applied or tested it.
> > > > However, it looks like it does the job.  In fact, its fairly
> > > > similar in parts to a patch, which adds LUKS2 keyfile and
> > > > detached header support, I've been waiting to send to the list
> > > > until the previous LUKS1 keyfile and detached header support
> > > > gets included (which my patches rely on).
> > > >
> > > > One implementation difference in this patch from the other one
> > > > is that this one passes the key file to recover_key as a
> > > > grub_file_t instead of passing the key contents.  I prefer the
> > > > previous method because it consolidates key file reading in
> > > > grub_cmd_cryptomount, whereas this patch requires each module
> > > > to do its own reading.  The disadvantage is this causes extra
> > > > code in the modules that could be consolidated and I don't see
> > > > much advantage to this.  By having grub_cmd_cryptomount do the
> > > > work we also get keyfile-offset and keyfile-size options in the
> > > > previous patch, for not much extra work.
> > > >
> > > > A minor nit, there is not error checking on grub_file_seek
> > > > calls and grub_file_read errors are occluded.  However, there
> > > > are some changes in this patch which I think make the code a
> > > > bit more aesthetically pleasing.
> > > >
> > > > While, I like that this patch allows for passing a master key
> > > > file, I think this feature should be build on the previous
> > > > patch series. So I don't recommend this patch be accepted.
> > > >
> > > > Glenn
> > > >
> > > > On Sat,  7 Nov 2020 19:36:35 +0300
> > > > reagentoo <reagentoo@gmail.com> wrote:
> > > >
> > > > > From: Dmitry Baranov <reagentoo@gmail.com>
> > > > >
> > > > > Hello.
> > > > > Could someone make initial review?
> > > > > The main difference between this patch and the previous ones
> > > > > is the ability to use a master key file with a detached
> > > > > header. This patch does not provide luks1 and geli support
> > > > > yet (luks2 only).
> > > > >
> > > > > Best Regards,
> > > > > Dmitry
> > > > >
> > > > > ---
> > > > >  grub-core/disk/cryptodisk.c |  99 +++++++++++++++-----
> > > > >  grub-core/disk/luks2.c      | 178
> > > > > ++++++++++++++++++++++++++++--------
> > > > > include/grub/cryptodisk.h   | 9 +- 3 files changed, 222
> > > > > insertions(+), 64 deletions(-)
> > > > >
> > > > > diff --git a/grub-core/disk/cryptodisk.c
> > > > > b/grub-core/disk/cryptodisk.c index 13af84dd1..987a39b16
> > > > > 100644 --- a/grub-core/disk/cryptodisk.c
> > > > > +++ b/grub-core/disk/cryptodisk.c
> > > > > @@ -41,6 +41,9 @@ static const struct grub_arg_option
> > > > > options[] = /* TRANSLATORS: It's still restricted to
> > > > > cryptodisks only. */ {"all", 'a', 0, N_("Mount all."), 0, 0},
> > > > >      {"boot", 'b', 0, N_("Mount all volumes with `boot' flag
> > > > > set."), 0, 0},
> > > > > +    {"header", 'H', 0, N_("Read header from file"), 0,
> > > > > ARG_TYPE_STRING},
> > > > > +    {"key-file", 'k', 0, N_("Read key from file"), 0,
> > > > > ARG_TYPE_STRING},
> > > > > +    {"master-key-file", 'K', 0, N_("Use a master key stored
> > > > > in a file"), 0, ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0}
> > > > >    };
> > > > >
> > > > > @@ -967,6 +970,7 @@ grub_util_cryptodisk_get_uuid (grub_disk_t
> > > > > disk)
> > > > >
> > > > >  static int check_boot, have_it;
> > > > >  static char *search_uuid;
> > > > > +static grub_file_t hdr_file, key_file, mkey_file;
> > > > >
> > > > >  static void
> > > > >  cryptodisk_close (grub_cryptodisk_t dev)
> > > > > @@ -991,13 +995,13 @@ grub_cryptodisk_scan_device_real (const
> > > > > char *name, grub_disk_t source)
> > > > >    FOR_CRYPTODISK_DEVS (cr)
> > > > >    {
> > > > > -    dev = cr->scan (source, search_uuid, check_boot);
> > > > > +    dev = cr->scan (source, hdr_file, search_uuid,
> > > > > check_boot); if (grub_errno)
> > > > >        return grub_errno;
> > > > >      if (!dev)
> > > > >        continue;
> > > > >
> > > > > -    err = cr->recover_key (source, dev);
> > > > > +    err = cr->recover_key (source, dev, hdr_file, key_file,
> > > > > mkey_file); if (err)
> > > > >      {
> > > > >        cryptodisk_close (dev);
> > > > > @@ -1038,7 +1042,7 @@ grub_cryptodisk_cheat_mount (const char
> > > > > *sourcedev, const char *cheat)
> > > > >    FOR_CRYPTODISK_DEVS (cr)
> > > > >    {
> > > > > -    dev = cr->scan (source, search_uuid, check_boot);
> > > > > +    dev = cr->scan (source, 0, search_uuid, check_boot);
> > > > >      if (grub_errno)
> > > > >        return grub_errno;
> > > > >      if (!dev)
> > > > > @@ -1087,11 +1091,59 @@ grub_cryptodisk_scan_device (const
> > > > > char *name, static grub_err_t
> > > > >  grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc,
> > > > > char **args) {
> > > > > +  grub_err_t ret = GRUB_ERR_NONE;
> > > > > +
> > > > >    struct grub_arg_list *state = ctxt->state;
> > > > >
> > > > >    if (argc < 1 && !state[1].set && !state[2].set)
> > > > >      return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name
> > > > > required");
> > > > > +  hdr_file = NULL;
> > > > > +  key_file = NULL;
> > > > > +  mkey_file = NULL;
> > > > > +
> > > > > +  if (state[3].set)
> > > > > +    {
> > > > > +      if (state[0].set)
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot use
> > > > > UUID lookup with detached header");
> > > > > +       goto err;
> > > > > +     }
> > > > > +
> > > > > +      hdr_file = grub_file_open (state[3].arg,
> > > > > GRUB_FILE_TYPE_NONE);
> > > > > +      if (!hdr_file)
> > > > > +     {
> > > > > +       ret = grub_errno;
> > > > > +       goto err;
> > > > > +     }
> > > > > +    }
> > > > > +
> > > > > +  if (state[4].set)
> > > > > +    {
> > > > > +      if (state[5].set)
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot use
> > > > > key with master key");
> > > > > +       goto err;
> > > > > +     }
> > > > > +
> > > > > +      key_file = grub_file_open (state[4].arg,
> > > > > GRUB_FILE_TYPE_NONE);
> > > > > +      if (!key_file)
> > > > > +     {
> > > > > +       ret = grub_errno;
> > > > > +       goto err;
> > > > > +     }
> > > > > +    }
> > > > > +
> > > > > +  if (state[5].set)
> > > > > +    {
> > > > > +      mkey_file = grub_file_open (state[5].arg,
> > > > > GRUB_FILE_TYPE_NONE);
> > > > > +      if (!mkey_file)
> > > > > +     {
> > > > > +       ret = grub_errno;
> > > > > +       goto err;
> > > > > +     }
> > > > > +    }
> > > > > +
> > > > >    have_it = 0;
> > > > >    if (state[0].set)
> > > > >      {
> > > > > @@ -1102,7 +1154,7 @@ grub_cmd_cryptomount
> > > > > (grub_extcmd_context_t ctxt, int argc, char **args) {
> > > > >         grub_dprintf ("cryptodisk",
> > > > >                       "already mounted as crypto%lu\n",
> > > > > dev->id);
> > > > > -       return GRUB_ERR_NONE;
> > > > > +       goto err;
> > > > >       }
> > > > >
> > > > >        check_boot = state[2].set;
> > > > > @@ -1111,8 +1163,11 @@ grub_cmd_cryptomount
> > > > > (grub_extcmd_context_t ctxt, int argc, char **args)
> > > > > search_uuid = NULL;
> > > > >
> > > > >        if (!have_it)
> > > > > -     return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such
> > > > > cryptodisk found");
> > > > > -      return GRUB_ERR_NONE;
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "no such
> > > > > cryptodisk found");
> > > > > +       goto err;
> > > > > +     }
> > > > > +      goto err;
> > > > >      }
> > > > >    else if (state[1].set || (argc == 0 && state[2].set))
> > > > >      {
> > > > > @@ -1120,11 +1175,10 @@ grub_cmd_cryptomount
> > > > > (grub_extcmd_context_t ctxt, int argc, char **args)
> > > > > check_boot = state[2].set; grub_device_iterate
> > > > > (&grub_cryptodisk_scan_device, NULL); search_uuid = NULL;
> > > > > -      return GRUB_ERR_NONE;
> > > > > +      goto err;
> > > > >      }
> > > > >    else
> > > > >      {
> > > > > -      grub_err_t err;
> > > > >        grub_disk_t disk;
> > > > >        grub_cryptodisk_t dev;
> > > > >        char *diskname;
> > > > > @@ -1147,27 +1201,30 @@ grub_cmd_cryptomount
> > > > > (grub_extcmd_context_t ctxt, int argc, char **args) {
> > > > >         if (disklast)
> > > > >           *disklast = ')';
> > > > > -       return grub_errno;
> > > > > +       ret = grub_errno;
> > > > > +       goto err;
> > > > >       }
> > > > >
> > > > >        dev = grub_cryptodisk_get_by_source_disk (disk);
> > > > >        if (dev)
> > > > > -     {
> > > > > -       grub_dprintf ("cryptodisk", "already mounted as
> > > > > crypto%lu\n", dev->id);
> > > > > -       grub_disk_close (disk);
> > > > > -       if (disklast)
> > > > > -         *disklast = ')';
> > > > > -       return GRUB_ERR_NONE;
> > > > > -     }
> > > > > -
> > > > > -      err = grub_cryptodisk_scan_device_real (diskname,
> > > > > disk);
> > > > > +     grub_dprintf ("cryptodisk", "already mounted as
> > > > > crypto%lu\n", dev->id);
> > > > > +      else
> > > > > +     ret = grub_cryptodisk_scan_device_real (diskname, disk);
> > > > >
> > > > >        grub_disk_close (disk);
> > > > >        if (disklast)
> > > > >       *disklast = ')';
> > > > > -
> > > > > -      return err;
> > > > >      }
> > > > > +
> > > > > + err:
> > > > > +  if (hdr_file)
> > > > > +    grub_file_close (hdr_file);
> > > > > +  if (key_file)
> > > > > +    grub_file_close (key_file);
> > > > > +  if (mkey_file)
> > > > > +    grub_file_close (mkey_file);
> > > > > +
> > > > > +  return ret;
> > > > >  }
> > > > >
> > > > >  static struct grub_disk_dev grub_cryptodisk_dev = {
> > > > > @@ -1299,7 +1356,7 @@ GRUB_MOD_INIT (cryptodisk)
> > > > >  {
> > > > >    grub_disk_dev_register (&grub_cryptodisk_dev);
> > > > >    cmd = grub_register_extcmd ("cryptomount",
> > > > > grub_cmd_cryptomount, 0,
> > > > > -                           N_("SOURCE|-u UUID|-a|-b"),
> > > > > +                           N_("SOURCE|-u UUID|-a|-b|-H
> > > > > file|-k file|-K file"), N_("Mount a crypto device."),
> > > > > options); grub_procfs_register ("luks_script", &luks_script);
> > > > >  }
> > > > > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > > > > index 31d7166fc..c29b472e6 100644
> > > > > --- a/grub-core/disk/luks2.c
> > > > > +++ b/grub-core/disk/luks2.c
> > > > > @@ -309,13 +309,22 @@ luks2_get_keyslot (grub_luks2_keyslot_t
> > > > > *k, grub_luks2_digest_t *d, grub_luks2_s
> > > > >  /* Determine whether to use primary or secondary header */
> > > > >  static grub_err_t
> > > > > -luks2_read_header (grub_disk_t disk, grub_luks2_header_t
> > > > > *outhdr) +luks2_read_header (grub_disk_t disk, grub_file_t
> > > > > hdr_file, grub_luks2_header_t *outhdr) {
> > > > >    grub_luks2_header_t primary, secondary, *header = &primary;
> > > > >    grub_err_t ret;
> > > > >
> > > > >    /* Read the primary LUKS header. */
> > > > > -  ret = grub_disk_read (disk, 0, 0, sizeof (primary),
> > > > > &primary);
> > > > > +  if (hdr_file)
> > > > > +    {
> > > > > +      grub_file_seek (hdr_file, 0);
> > > > > +      if (grub_file_read (hdr_file, &primary, sizeof
> > > > > (primary)) != sizeof (primary))
> > > > > +       ret = GRUB_ERR_READ_ERROR;
> > > > > +      else
> > > > > +       ret = GRUB_ERR_NONE;
> > > > > +    }
> > > > > +  else
> > > > > +      ret = grub_disk_read (disk, 0, 0, sizeof (primary),
> > > > > &primary); if (ret)
> > > > >      return ret;
> > > > >
> > > > > @@ -325,7 +334,16 @@ luks2_read_header (grub_disk_t disk,
> > > > > grub_luks2_header_t *outhdr) return GRUB_ERR_BAD_SIGNATURE;
> > > > >
> > > > >    /* Read the secondary header. */
> > > > > -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64
> > > > > (primary.hdr_size), sizeof (secondary), &secondary);
> > > > > +  if (hdr_file)
> > > > > +    {
> > > > > +      grub_file_seek (hdr_file, grub_be_to_cpu64
> > > > > (primary.hdr_size));
> > > > > +      if (grub_file_read (hdr_file, &secondary, sizeof
> > > > > (secondary)) != sizeof (secondary))
> > > > > +       ret = GRUB_ERR_READ_ERROR;
> > > > > +      else
> > > > > +       ret = GRUB_ERR_NONE;
> > > > > +    }
> > > > > +  else
> > > > > +      ret = grub_disk_read (disk, 0, grub_be_to_cpu64
> > > > > (primary.hdr_size), sizeof (secondary), &secondary); if (ret)
> > > > >      return ret;
> > > > >
> > > > > @@ -342,7 +360,7 @@ luks2_read_header (grub_disk_t disk,
> > > > > grub_luks2_header_t *outhdr) }
> > > > >
> > > > >  static grub_cryptodisk_t
> > > > > -luks2_scan (grub_disk_t disk, const char *check_uuid, int
> > > > > check_boot) +luks2_scan (grub_disk_t disk, grub_file_t
> > > > > hdr_file, const char *check_uuid, int check_boot) {
> > > > >    grub_cryptodisk_t cryptodisk;
> > > > >    grub_luks2_header_t header;
> > > > > @@ -352,7 +370,7 @@ luks2_scan (grub_disk_t disk, const char
> > > > > *check_uuid, int check_boot) if (check_boot)
> > > > >      return NULL;
> > > > >
> > > > > -  if (luks2_read_header (disk, &header))
> > > > > +  if (luks2_read_header (disk, hdr_file, &header))
> > > > >      {
> > > > >        grub_errno = GRUB_ERR_NONE;
> > > > >        return NULL;
> > > > > @@ -415,7 +433,7 @@ luks2_verify_key (grub_luks2_digest_t *d,
> > > > > grub_uint8_t *candidate_key,
> > > > >  static grub_err_t
> > > > >  luks2_decrypt_key (grub_uint8_t *out_key,
> > > > > -                grub_disk_t disk, grub_cryptodisk_t crypt,
> > > > > +                grub_disk_t disk, grub_cryptodisk_t crypt,
> > > > > grub_file_t hdr_file, grub_luks2_keyslot_t *k,
> > > > >                  const grub_uint8_t *passphrase, grub_size_t
> > > > > passphraselen) {
> > > > > @@ -491,7 +509,16 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> > > > >      }
> > > > >
> > > > >    grub_errno = GRUB_ERR_NONE;
> > > > > -  ret = grub_disk_read (disk, 0, k->area.offset,
> > > > > k->area.size, split_key);
> > > > > +  if (hdr_file)
> > > > > +    {
> > > > > +      grub_file_seek (hdr_file, k->area.offset);
> > > > > +      if (grub_file_read (hdr_file, split_key, k->area.size)
> > > > > != k->area.size)
> > > > > +       ret = GRUB_ERR_READ_ERROR;
> > > > > +      else
> > > > > +       ret = GRUB_ERR_NONE;
> > > > > +    }
> > > > > +  else
> > > > > +      ret = grub_disk_read (disk, 0, k->area.offset,
> > > > > k->area.size, split_key); if (ret)
> > > > >      {
> > > > >        grub_error (GRUB_ERR_IO, "Read error: %s\n",
> > > > > grub_errmsg); @@ -531,12 +558,16 @@ luks2_decrypt_key
> > > > > (grub_uint8_t *out_key,
> > > > >
> > > > >  static grub_err_t
> > > > >  luks2_recover_key (grub_disk_t disk,
> > > > > -                grub_cryptodisk_t crypt)
> > > > > +                grub_cryptodisk_t crypt,
> > > > > +                grub_file_t hdr_file, grub_file_t key_file,
> > > > > grub_file_t mkey_file) {
> > > > > +  char cipher[32];
> > > > > +  char *passphrase = NULL;
> > > > >    grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
> > > > > -  char passphrase[MAX_PASSPHRASE], cipher[32];
> > > > > +  grub_size_t candidate_key_len, passphrase_len;
> > > > >    char *json_header = NULL, *part = NULL, *ptr;
> > > > > -  grub_size_t candidate_key_len = 0, i, size;
> > > > > +  grub_off_t json_header_offset;
> > > > > +  grub_size_t json_header_size, i, size;
> > > > >    grub_luks2_header_t header;
> > > > >    grub_luks2_keyslot_t keyslot;
> > > > >    grub_luks2_digest_t digest;
> > > > > @@ -545,7 +576,7 @@ luks2_recover_key (grub_disk_t disk,
> > > > >    grub_json_t *json = NULL, keyslots;
> > > > >    grub_err_t ret;
> > > > >
> > > > > -  ret = luks2_read_header (disk, &header);
> > > > > +  ret = luks2_read_header (disk, hdr_file, &header);
> > > > >    if (ret)
> > > > >      return ret;
> > > > >
> > > > > @@ -554,8 +585,19 @@ luks2_recover_key (grub_disk_t disk,
> > > > >        return GRUB_ERR_OUT_OF_MEMORY;
> > > > >
> > > > >    /* Read the JSON area. */
> > > > > -  ret = grub_disk_read (disk, 0, grub_be_to_cpu64
> > > > > (header.hdr_offset) + sizeof (header),
> > > > > -                     grub_be_to_cpu64 (header.hdr_size) -
> > > > > sizeof (header), json_header);
> > > > > +  json_header_offset = grub_be_to_cpu64 (header.hdr_offset) +
> > > > > sizeof (header);
> > > > > +  json_header_size = grub_be_to_cpu64 (header.hdr_size) -
> > > > > sizeof (header); +
> > > > > +  if (hdr_file)
> > > > > +    {
> > > > > +      grub_file_seek (hdr_file, json_header_offset);
> > > > > +      if (grub_file_read (hdr_file, json_header,
> > > > > json_header_size) != json_header_size)
> > > > > +       ret = GRUB_ERR_READ_ERROR;
> > > > > +      else
> > > > > +       ret = GRUB_ERR_NONE;
> > > > > +    }
> > > > > +  else
> > > > > +      ret = grub_disk_read (disk, 0, json_header_offset,
> > > > > json_header_size, json_header); if (ret)
> > > > >        goto err;
> > > > >
> > > > > @@ -570,16 +612,47 @@ luks2_recover_key (grub_disk_t disk,
> > > > >        goto err;
> > > > >      }
> > > > >
> > > > > -  /* Get the passphrase from the user. */
> > > > > -  if (disk->partition)
> > > > > -    part = grub_partition_get_name (disk->partition);
> > > > > -  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "),
> > > > > disk->name,
> > > > > -             disk->partition ? "," : "", part ? : "",
> > > > > -             crypt->uuid);
> > > > > -  if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> > > > > +  if (mkey_file)
> > > > >      {
> > > > > -      ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase
> > > > > not supplied");
> > > > > -      goto err;
> > > > > +      /* Get the master key from file. */
> > > > > +      candidate_key_len = grub_file_read (mkey_file,
> > > > > candidate_key, GRUB_CRYPTODISK_MAX_KEYLEN);
> > > > > +      if (candidate_key_len == (grub_size_t)-1)
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_FILE_READ_ERROR, "Error
> > > > > reading key file");
> > > > > +       goto err;
> > > > > +     }
> > > > > +      if (candidate_key_len == 0)
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Key not
> > > > > supplied");
> > > > > +       goto err;
> > > > > +     }
> > > > > +    }
> > > > > +  else if (key_file)
> > > > > +    {
> > > > > +      /* Get the passphrase from file. */
> > > > > +      passphrase = grub_malloc
> > > > > (GRUB_CRYPTODISK_MAX_PASSPHRASE);
> > > > > +      passphrase_len = grub_file_read (key_file, passphrase,
> > > > > GRUB_CRYPTODISK_MAX_PASSPHRASE);
> > > > > +      if (passphrase_len == (grub_size_t)-1)
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_FILE_READ_ERROR, "Error
> > > > > reading passphrase file");
> > > > > +       goto err;
> > > > > +     }
> > > > > +    }
> > > > > +  else
> > > > > +    {
> > > > > +      /* Get the passphrase from the user. */
> > > > > +      if (disk->partition)
> > > > > +     part = grub_partition_get_name (disk->partition);
> > > > > +      grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "),
> > > > > disk->name,
> > > > > +                 disk->partition ? "," : "", part ? : "",
> > > > > +                 crypt->uuid);
> > > > > +      passphrase = grub_malloc (MAX_PASSPHRASE);
> > > > > +      if (!grub_password_get (passphrase, MAX_PASSPHRASE))
> > > > > +     {
> > > > > +       ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase
> > > > > not supplied");
> > > > > +       goto err;
> > > > > +     }
> > > > > +      passphrase_len = grub_strlen (passphrase);
> > > > >      }
> > > > >
> > > > >    if (grub_json_getvalue (&keyslots, json, "keyslots") ||
> > > > > @@ -604,6 +677,26 @@ luks2_recover_key (grub_disk_t disk,
> > > > >
> > > > >        grub_dprintf ("luks2", "Trying keyslot
> > > > > %"PRIuGRUB_SIZE"\n", i);
> > > > >
> > > > > +      if (mkey_file)
> > > > > +     {
> > > > > +       if (candidate_key_len != keyslot.key_size)
> > > > > +         {
> > > > > +           grub_dprintf ("luks2", "Wrong key length for
> > > > > keyslot %"PRIuGRUB_SIZE": %s\n",
> > > > > +                         i, grub_errmsg);
> > > > > +           continue;
> > > > > +         }
> > > > > +
> > > > > +       ret = luks2_verify_key (&digest, candidate_key,
> > > > > candidate_key_len);
> > > > > +       if (ret)
> > > > > +         {
> > > > > +           grub_dprintf ("luks2", "Could not open keyslot
> > > > > %"PRIuGRUB_SIZE": %s\n",
> > > > > +                         i, grub_errmsg);
> > > > > +           continue;
> > > > > +         }
> > > > > +     }
> > > > > +      else
> > > > > +       candidate_key_len = keyslot.key_size;
> > > > > +
> > > > >        /* Set up disk according to keyslot's segment. */
> > > > >        crypt->offset = grub_divmod64 (segment.offset,
> > > > > segment.sector_size, NULL); crypt->log_sector_size = sizeof
> > > > > (unsigned int) * 8 @@ -613,21 +706,24 @@ luks2_recover_key
> > > > > (grub_disk_t disk, else
> > > > >       crypt->total_length = grub_strtoull (segment.size, NULL,
> > > > > 10);
> > > > >
> > > > > -      ret = luks2_decrypt_key (candidate_key, disk, crypt,
> > > > > &keyslot,
> > > > > -                            (const grub_uint8_t *)
> > > > > passphrase, grub_strlen (passphrase));
> > > > > -      if (ret)
> > > > > +      if (passphrase)
> > > > >       {
> > > > > -       grub_dprintf ("luks2", "Decryption with keyslot
> > > > > %"PRIuGRUB_SIZE" failed: %s\n",
> > > > > -                     i, grub_errmsg);
> > > > > -       continue;
> > > > > -     }
> > > > > -
> > > > > -      ret = luks2_verify_key (&digest, candidate_key,
> > > > > keyslot.key_size);
> > > > > -      if (ret)
> > > > > -     {
> > > > > -       grub_dprintf ("luks2", "Could not open keyslot
> > > > > %"PRIuGRUB_SIZE": %s\n",
> > > > > -                     i, grub_errmsg);
> > > > > -       continue;
> > > > > +       ret = luks2_decrypt_key (candidate_key, disk, crypt,
> > > > > hdr_file, &keyslot,
> > > > > +                                (const grub_uint8_t *)
> > > > > passphrase, passphrase_len);
> > > > > +       if (ret)
> > > > > +         {
> > > > > +           grub_dprintf ("luks2", "Decryption with keyslot
> > > > > %"PRIuGRUB_SIZE" failed: %s\n",
> > > > > +                         i, grub_errmsg);
> > > > > +           continue;
> > > > > +         }
> > > > > +
> > > > > +       ret = luks2_verify_key (&digest, candidate_key,
> > > > > candidate_key_len);
> > > > > +       if (ret)
> > > > > +         {
> > > > > +           grub_dprintf ("luks2", "Could not open keyslot
> > > > > %"PRIuGRUB_SIZE": %s\n",
> > > > > +                         i, grub_errmsg);
> > > > > +           continue;
> > > > > +         }
> > > > >       }
> > > > >
> > > > >        /*
> > > > > @@ -635,13 +731,14 @@ luks2_recover_key (grub_disk_t disk,
> > > > >         * where each element is either empty or holds a key.
> > > > >         */
> > > > >        grub_printf_ (N_("Slot %"PRIuGRUB_SIZE" opened\n"), i);
> > > > > -
> > > > > -      candidate_key_len = keyslot.key_size;
> > > > >        break;
> > > > >      }
> > > > > -  if (candidate_key_len == 0)
> > > > > +  if (i == size)
> > > > >      {
> > > > > -      ret = grub_error (GRUB_ERR_ACCESS_DENIED, "Invalid
> > > > > passphrase");
> > > > > +      if (mkey_file)
> > > > > +       ret = grub_error (GRUB_ERR_ACCESS_DENIED, "Invalid
> > > > > key");
> > > > > +      else
> > > > > +       ret = grub_error (GRUB_ERR_ACCESS_DENIED, "Invalid
> > > > > passphrase"); goto err;
> > > > >      }
> > > > >
> > > > > @@ -666,6 +763,7 @@ luks2_recover_key (grub_disk_t disk,
> > > > >
> > > > >   err:
> > > > >    grub_free (part);
> > > > > +  grub_free (passphrase);
> > > > >    grub_free (json_header);
> > > > >    grub_json_free (json);
> > > > >    return ret;
> > > > > diff --git a/include/grub/cryptodisk.h
> > > > > b/include/grub/cryptodisk.h index e1b21e785..b53006854 100644
> > > > > --- a/include/grub/cryptodisk.h
> > > > > +++ b/include/grub/cryptodisk.h
> > > > > @@ -21,6 +21,7 @@
> > > > >
> > > > >  #include <grub/disk.h>
> > > > >  #include <grub/crypto.h>
> > > > > +#include <grub/file.h>
> > > > >  #include <grub/list.h>
> > > > >  #ifdef GRUB_UTIL
> > > > >  #include <grub/emu/hostdisk.h>
> > > > > @@ -53,6 +54,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 8192
> > > > >
> > > > >  struct grub_cryptodisk;
> > > > >
> > > > > @@ -106,9 +108,10 @@ struct grub_cryptodisk_dev
> > > > >    struct grub_cryptodisk_dev *next;
> > > > >    struct grub_cryptodisk_dev **prev;
> > > > >
> > > > > -  grub_cryptodisk_t (*scan) (grub_disk_t disk, const char
> > > > > *check_uuid,
> > > > > -                          int boot_only);
> > > > > -  grub_err_t (*recover_key) (grub_disk_t disk,
> > > > > grub_cryptodisk_t dev);
> > > > > +  grub_cryptodisk_t (*scan) (grub_disk_t disk, grub_file_t
> > > > > hdr_file,
> > > > > +                          const char *check_uuid, int
> > > > > boot_only);
> > > > > +  grub_err_t (*recover_key) (grub_disk_t disk,
> > > > > grub_cryptodisk_t dev,
> > > > > +                          grub_file_t hdr_file, grub_file_t
> > > > > key_file, grub_file_t mkey_file); };
> > > > >  typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
> > > > >
> > > >



reply via email to

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