[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v5 2/2] luks2: Fix decoding of digests and salts with escaped
From: |
Patrick Steinhardt |
Subject: |
Re: [PATCH v5 2/2] luks2: Fix decoding of digests and salts with escaped chars |
Date: |
Tue, 12 Jul 2022 16:09:18 +0200 |
On Tue, Jul 12, 2022 at 03:30:22PM +0200, Daniel Kiper wrote:
> On Mon, Jul 11, 2022 at 12:44:59PM +0200, Patrick Steinhardt wrote:
> > It was reported in the #grub IRC channel on Libera that decryption of
> > LUKS2 partitions fails with errors about invalid digests and/or salts.
> > In all of these cases, what failed was decoding the Base64
> > representation of these, where the encoded data contained invalid
> > characters.
> >
> > As it turns out, the root cause is that json-c, which is used by
> > cryptsetup to read and write the JSON header, will escape some
> > characters by prepending a backslash when writing JSON strings by
> > default. Most importantly, json-c also escapes the forward slash, which
> > is part of the Base64 alphabet. Because GRUB doesn't know to unescape
> > such characters, decoding this string will rightfully fail.
> >
> > Interestingly, this issue has until now only been reported by users of
> > Ubuntu 18.04. And a bit of digging in fact reveals that cryptsetup has
> > changed the logic in a054206d (Suppress useless slash escaping in json
> > lib, 2018-04-20), which has been released with cryptsetup v2.0.3. Ubuntu
> > 18.04 is still shipping with cryptsetup v2.0.2 though, which explains
> > why this is not a more frequent issue.
> >
> > Fix the issue by using our new `grub_json_unescape ()` helper function
> > that handles unescaping for us.
> >
> > Reported-by: Afdal
>
> Any chance to add this guy email here?
He didn't want his mail address to be associated with his name here.
> > Signed-off-by: Patrick Steinhardt <ps@pks.im>
> > ---
> > grub-core/disk/luks2.c | 28 ++++++++++++++++++++++++----
> > 1 file changed, 24 insertions(+), 4 deletions(-)
> >
> > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
> > index bf741d70f..c24c6e98d 100644
> > --- a/grub-core/disk/luks2.c
> > +++ b/grub-core/disk/luks2.c
> > @@ -384,6 +384,24 @@ luks2_scan (grub_disk_t disk, grub_cryptomount_args_t
> > cargs)
> > return cryptodisk;
> > }
> >
> > +static grub_err_t
> > +luks2_base64_decode (const char *in, grub_size_t inlen, grub_uint8_t
> > *decoded, idx_t *decodedlen)
> > +{
> > + grub_size_t unescaped_len = 0;
> > + char *unescaped = NULL;
> > + bool successful;
> > +
> > + if (grub_json_unescape (&unescaped, &unescaped_len, in, inlen) !=
> > GRUB_ERR_NONE)
> > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("could not unescape
> > Base64 string"));
> > +
> > + successful = base64_decode (unescaped, (grub_size_t) unescaped_len,
> > (char *) decoded, decodedlen);
>
> Now (grub_size_t) cast seems redundant because unescaped_len is defined
> as grub_size_t.
>
> Otherwise patch LGTM. So, if you fix this you can add my RB.
Oops, right. Will fix.
Patrick
> > + grub_free (unescaped);
> > + if (!successful)
> > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("could not decode Base64
> > string"));
> > +
> > + return GRUB_ERR_NONE;
> > +}
> > +
> > static grub_err_t
> > luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key,
> > grub_size_t candidate_key_len)
> > @@ -395,9 +413,11 @@ luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t
> > *candidate_key,
> > gcry_err_code_t gcry_ret;
> >
> > /* Decode both digest and salt */
> > - if (!base64_decode (d->digest, grub_strlen (d->digest), (char *)digest,
> > &digestlen))
> > + if (luks2_base64_decode (d->digest, grub_strlen (d->digest),
> > + digest, &digestlen) != GRUB_ERR_NONE)
> > return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest");
> > - if (!base64_decode (d->salt, grub_strlen (d->salt), (char *)salt,
> > &saltlen))
> > + if (luks2_base64_decode (d->salt, grub_strlen (d->salt),
> > + salt, &saltlen) != GRUB_ERR_NONE)
> > return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest salt");
> >
> > /* Configure the hash used for the digest. */
> > @@ -435,8 +455,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
> > gcry_err_code_t gcry_ret;
> > grub_err_t ret;
> >
> > - if (!base64_decode (k->kdf.salt, grub_strlen (k->kdf.salt),
> > - (char *)salt, &saltlen))
> > + if (luks2_base64_decode (k->kdf.salt, grub_strlen (k->kdf.salt),
> > + salt, &saltlen) != GRUB_ERR_NONE)
> > {
> > ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot salt");
> > goto err;
>
> Daniel
signature.asc
Description: PGP signature