* [PATCH] verify: search keyid in hashed signature subpackets (repost) @ 2016-11-18 12:00 Ignat Korchagin 2016-11-21 14:45 ` Daniel Kiper 0 siblings, 1 reply; 14+ messages in thread From: Ignat Korchagin @ 2016-11-18 12:00 UTC (permalink / raw) To: grub-devel; +Cc: Ignat Korchagin Reposting this, as requested by Daniel and rebasing on current tree. Currently GRUB2 verify logic searches PGP keyid only in unhashed subpackets of PGP signature packet. As a result, signatures generated with GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could not be verified, because this package puts keyid in hashed subpackets and GRUB code never initializes the keyid variable, therefore is not able to find "verification key" with id 0x0. Signed-off-by: Ignat Korchagin <ignat@cloudflare.com> --- grub-core/commands/verify.c | 115 +++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 39 deletions(-) diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c index 67cb1c7..1b628b2 100644 --- a/grub-core/commands/verify.c +++ b/grub-core/commands/verify.c @@ -445,6 +445,38 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, return ret; } +static grub_uint64_t +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) +{ + const grub_uint8_t *ptr; + grub_uint32_t l; + grub_uint64_t keyid = 0; + + for (ptr = sub; ptr < sub + sub_len; ptr += l) + { + if (*ptr < 192) + l = *ptr++; + else if (*ptr < 255) + { + if (ptr + 1 >= sub + sub_len) + break; + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; + ptr += 2; + } + else + { + if (ptr + 5 >= sub + sub_len) + break; + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); + ptr += 5; + } + if (*ptr == 0x10 && l >= 8) + keyid = grub_get_unaligned64 (ptr + 1); + } + + return keyid; +} + static grub_err_t grub_verify_signature_real (char *buf, grub_size_t size, grub_file_t f, grub_file_t sig, @@ -529,20 +561,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, break; hash->write (context, readbuf, r); } + grub_free (readbuf); + + readbuf = grub_malloc (rem); + if (!readbuf) + goto fail; hash->write (context, &v, sizeof (v)); hash->write (context, &v4, sizeof (v4)); - while (rem) + + r = 0; + while (r < rem) { - r = grub_file_read (sig, readbuf, - rem < READBUF_SIZE ? rem : READBUF_SIZE); - if (r < 0) - goto fail; - if (r == 0) + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); + if (rr < 0) + goto fail; + if (rr == 0) break; - hash->write (context, readbuf, r); - rem -= r; + r += rr; } + if (r != rem) + goto fail; + hash->write (context, readbuf, rem); + keyid = grub_subpacket_keyid_search (readbuf, rem); + grub_free (readbuf); + hash->write (context, &v, sizeof (v)); s = 0xff; hash->write (context, &s, sizeof (s)); @@ -550,40 +593,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); if (r != sizeof (unhashed_sub)) goto fail; - { - grub_uint8_t *ptr; - grub_uint32_t l; - rem = grub_be_to_cpu16 (unhashed_sub); - if (rem > READBUF_SIZE) - goto fail; - r = grub_file_read (sig, readbuf, rem); - if (r != rem) - goto fail; - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) - { - if (*ptr < 192) - l = *ptr++; - else if (*ptr < 255) - { - if (ptr + 1 >= readbuf + rem) - break; - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; - ptr += 2; - } - else - { - if (ptr + 5 >= readbuf + rem) - break; - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); - ptr += 5; - } - if (*ptr == 0x10 && l >= 8) - keyid = grub_get_unaligned64 (ptr + 1); - } - } + rem = grub_be_to_cpu16 (unhashed_sub); + readbuf = grub_malloc (rem); + if (!readbuf) + goto fail; + + r = 0; + while (r < rem) + { + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); + if (rr < 0) + goto fail; + if (rr == 0) + break; + r += rr; + } + if (r != rem) + goto fail; + + if (keyid == 0) + keyid = grub_subpacket_keyid_search (readbuf, rem); + grub_free (readbuf); hash->final (context); + readbuf = grub_zalloc (READBUF_SIZE); + if (!readbuf) + goto fail; + grub_dprintf ("crypt", "alive\n"); hval = hash->read (context); -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-18 12:00 [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin @ 2016-11-21 14:45 ` Daniel Kiper 2016-11-21 17:56 ` Jon McCune 2016-11-21 22:25 ` [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin 0 siblings, 2 replies; 14+ messages in thread From: Daniel Kiper @ 2016-11-21 14:45 UTC (permalink / raw) To: ignat, grub-devel; +Cc: arvidjaar On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: > Reposting this, as requested by Daniel and rebasing on current tree. > > Currently GRUB2 verify logic searches PGP keyid only in unhashed subpackets of PGP signature packet. As a result, signatures generated with GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could not be verified, because this package puts keyid in hashed subpackets and GRUB code never initializes the keyid variable, therefore is not able to find "verification key" with id 0x0. > > Signed-off-by: Ignat Korchagin <ignat@cloudflare.com> > --- > grub-core/commands/verify.c | 115 +++++++++++++++++++++++++++++--------------- > 1 file changed, 76 insertions(+), 39 deletions(-) > > diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c > index 67cb1c7..1b628b2 100644 > --- a/grub-core/commands/verify.c > +++ b/grub-core/commands/verify.c > @@ -445,6 +445,38 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, > return ret; > } > > +static grub_uint64_t > +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) > +{ > + const grub_uint8_t *ptr; > + grub_uint32_t l; > + grub_uint64_t keyid = 0; > + > + for (ptr = sub; ptr < sub + sub_len; ptr += l) > + { > + if (*ptr < 192) Please define some constants and use them properly... > + l = *ptr++; > + else if (*ptr < 255) Ditto. > + { > + if (ptr + 1 >= sub + sub_len) > + break; > + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; Ditto. > + ptr += 2; Ditto and below... > + } > + else > + { > + if (ptr + 5 >= sub + sub_len) > + break; > + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); > + ptr += 5; > + } > + if (*ptr == 0x10 && l >= 8) > + keyid = grub_get_unaligned64 (ptr + 1); > + } > + > + return keyid; > +} > + > static grub_err_t > grub_verify_signature_real (char *buf, grub_size_t size, > grub_file_t f, grub_file_t sig, > @@ -529,20 +561,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, > break; > hash->write (context, readbuf, r); > } > + grub_free (readbuf); > + > + readbuf = grub_malloc (rem); grub_zalloc()? > + if (!readbuf) > + goto fail; > > hash->write (context, &v, sizeof (v)); > hash->write (context, &v4, sizeof (v4)); > - while (rem) > + > + r = 0; > + while (r < rem) > { > - r = grub_file_read (sig, readbuf, > - rem < READBUF_SIZE ? rem : READBUF_SIZE); > - if (r < 0) > - goto fail; > - if (r == 0) > + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); > + if (rr < 0) > + goto fail; > + if (rr == 0) > break; > - hash->write (context, readbuf, r); > - rem -= r; > + r += rr; > } > + if (r != rem) > + goto fail; > + hash->write (context, readbuf, rem); > + keyid = grub_subpacket_keyid_search (readbuf, rem); > + grub_free (readbuf); > + > hash->write (context, &v, sizeof (v)); > s = 0xff; > hash->write (context, &s, sizeof (s)); > @@ -550,40 +593,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, > r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); > if (r != sizeof (unhashed_sub)) > goto fail; > - { > - grub_uint8_t *ptr; > - grub_uint32_t l; > - rem = grub_be_to_cpu16 (unhashed_sub); > - if (rem > READBUF_SIZE) > - goto fail; > - r = grub_file_read (sig, readbuf, rem); > - if (r != rem) > - goto fail; > - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) > - { > - if (*ptr < 192) > - l = *ptr++; > - else if (*ptr < 255) > - { > - if (ptr + 1 >= readbuf + rem) > - break; > - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; > - ptr += 2; > - } > - else > - { > - if (ptr + 5 >= readbuf + rem) > - break; > - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); > - ptr += 5; > - } > - if (*ptr == 0x10 && l >= 8) > - keyid = grub_get_unaligned64 (ptr + 1); > - } > - } > + rem = grub_be_to_cpu16 (unhashed_sub); > + readbuf = grub_malloc (rem); grub_zalloc()? Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-21 14:45 ` Daniel Kiper @ 2016-11-21 17:56 ` Jon McCune 2016-11-21 22:31 ` Ignat Korchagin 2016-11-21 22:25 ` [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin 1 sibling, 1 reply; 14+ messages in thread From: Jon McCune @ 2016-11-21 17:56 UTC (permalink / raw) To: The development of GNU GRUB; +Cc: ignat, Andrey Borzenkov [-- Attachment #1: Type: text/plain, Size: 914 bytes --] On Mon, Nov 21, 2016 at 6:45 AM, Daniel Kiper <dkiper@net-space.pl> wrote: > On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: > > Reposting this, as requested by Daniel and rebasing on current tree. > > > > Currently GRUB2 verify logic searches PGP keyid only in unhashed > subpackets of PGP signature packet. As a result, signatures generated with > GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) > could not be verified, because this package puts keyid in hashed subpackets > and GRUB code never initializes the keyid variable, therefore is not able > to find "verification key" with id 0x0. > I think it would be wise to include a brief argument citing the OpenPGP RFC that this change is compliant. Compatibility with an existing implementation is valuable, but let's make sure the appropriate code is being changed. (I haven't looked carefully myself.) Thanks, -Jon [-- Attachment #2: Type: text/html, Size: 1413 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-21 17:56 ` Jon McCune @ 2016-11-21 22:31 ` Ignat Korchagin 2016-11-22 8:28 ` Daniel Kiper 0 siblings, 1 reply; 14+ messages in thread From: Ignat Korchagin @ 2016-11-21 22:31 UTC (permalink / raw) To: Jon McCune; +Cc: The development of GNU GRUB, Andrey Borzenkov, Daniel Kiper On Mon, Nov 21, 2016 at 6:56 PM, Jon McCune <jonmccune@google.com> wrote: > On Mon, Nov 21, 2016 at 6:45 AM, Daniel Kiper <dkiper@net-space.pl> wrote: >> >> On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: >> > Reposting this, as requested by Daniel and rebasing on current tree. >> > >> > Currently GRUB2 verify logic searches PGP keyid only in unhashed >> > subpackets of PGP signature packet. As a result, signatures generated with >> > GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could >> > not be verified, because this package puts keyid in hashed subpackets and >> > GRUB code never initializes the keyid variable, therefore is not able to >> > find "verification key" with id 0x0. > > > I think it would be wise to include a brief argument citing the OpenPGP RFC > that this change is compliant. Compatibility with an existing implementation > is valuable, but let's make sure the appropriate code is being changed. (I > haven't looked carefully myself.) > > Thanks, > -Jon > > This change is compliant with RFC 4880. According to p 5.2.3 only "Signature Creation Time" subpacket "MUST be present in the hashed area". All other subpacket types may be present either in hashed or unhashed areas. Currently, GRUB assumes, that the "Issuer" subpacket is in unhashed area (by default put there by gpg tool), but other PGP implementations like (https://godoc.org/golang.org/x/crypto/openpgp) may put it in the hashed area. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-21 22:31 ` Ignat Korchagin @ 2016-11-22 8:28 ` Daniel Kiper 2016-12-02 16:58 ` [PATCH v2] verify: search keyid in hashed signature subpackets Ignat Korchagin 0 siblings, 1 reply; 14+ messages in thread From: Daniel Kiper @ 2016-11-22 8:28 UTC (permalink / raw) To: ignat, grub-devel; +Cc: jonmccune, arvidjaar, dkiper On Mon, Nov 21, 2016 at 11:31:26PM +0100, Ignat Korchagin wrote: > On Mon, Nov 21, 2016 at 6:56 PM, Jon McCune <jonmccune@google.com> wrote: > > On Mon, Nov 21, 2016 at 6:45 AM, Daniel Kiper <dkiper@net-space.pl> wrote: > >> > >> On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: > >> > Reposting this, as requested by Daniel and rebasing on current tree. > >> > > >> > Currently GRUB2 verify logic searches PGP keyid only in unhashed > >> > subpackets of PGP signature packet. As a result, signatures generated with > >> > GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could > >> > not be verified, because this package puts keyid in hashed subpackets and > >> > GRUB code never initializes the keyid variable, therefore is not able to > >> > find "verification key" with id 0x0. > > > > > > I think it would be wise to include a brief argument citing the OpenPGP RFC > > that this change is compliant. Compatibility with an existing implementation > > is valuable, but let's make sure the appropriate code is being changed. (I > > haven't looked carefully myself.) > > > > Thanks, > > -Jon > > > > > > This change is compliant with RFC 4880. According to p 5.2.3 only > "Signature Creation Time" subpacket "MUST be present in the hashed > area". All other subpacket types may be present either in hashed or > unhashed areas. Currently, GRUB assumes, that the "Issuer" subpacket > is in unhashed area (by default put there by gpg tool), but other PGP > implementations like (https://godoc.org/golang.org/x/crypto/openpgp) > may put it in the hashed area. Please add this to commit message. Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2] verify: search keyid in hashed signature subpackets 2016-11-22 8:28 ` Daniel Kiper @ 2016-12-02 16:58 ` Ignat Korchagin 2016-12-05 15:24 ` Daniel Kiper 2016-12-10 17:59 ` Andrei Borzenkov 0 siblings, 2 replies; 14+ messages in thread From: Ignat Korchagin @ 2016-12-02 16:58 UTC (permalink / raw) To: grub-devel; +Cc: Ignat Korchagin, Daniel Kiper According to RFC 4880 5.2.3 only "Signature Creation Time" subpacket "MUST" be present in the hashed area. All other subpacket types may be present either in hashed or unhashed areas. Currently GRUB assumes, that the "Issuer" subpacket is in unhashed area (by default put there by gpg tool), but other PGP implementations (like https://godoc.org/golang.org/x/crypto/openpgp) may put it in the hashed area. --- grub-core/commands/verify.c | 122 ++++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 39 deletions(-) diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c index 67cb1c7..79b3826 100644 --- a/grub-core/commands/verify.c +++ b/grub-core/commands/verify.c @@ -33,6 +33,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* RFC 4880 5.2.3.1 */ +#define OPENPGP_SIGNATURE_SUBPACKET_TYPE 16 + struct grub_verified { grub_file_t file; @@ -445,6 +448,42 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, return ret; } +/* + * Parsing algorithm from RFC 4880 5.2.3.1 + */ + +static grub_uint64_t +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) +{ + const grub_uint8_t *ptr; + grub_uint32_t l; + grub_uint64_t keyid = 0; + + for (ptr = sub; ptr < sub + sub_len; ptr += l) + { + if (*ptr < 192) + l = *ptr++; + else if (*ptr < 255) + { + if (ptr + 1 >= sub + sub_len) + break; + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; + ptr += 2; + } + else + { + if (ptr + 5 >= sub + sub_len) + break; + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); + ptr += 5; + } + if (*ptr == OPENPGP_SIGNATURE_SUBPACKET_TYPE && l >= 8) + keyid = grub_get_unaligned64 (ptr + 1); + } + + return keyid; +} + static grub_err_t grub_verify_signature_real (char *buf, grub_size_t size, grub_file_t f, grub_file_t sig, @@ -529,20 +568,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, break; hash->write (context, readbuf, r); } + grub_free (readbuf); + + readbuf = grub_malloc (rem); + if (!readbuf) + goto fail; hash->write (context, &v, sizeof (v)); hash->write (context, &v4, sizeof (v4)); - while (rem) + + r = 0; + while (r < rem) { - r = grub_file_read (sig, readbuf, - rem < READBUF_SIZE ? rem : READBUF_SIZE); - if (r < 0) - goto fail; - if (r == 0) + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); + if (rr < 0) + goto fail; + if (rr == 0) break; - hash->write (context, readbuf, r); - rem -= r; + r += rr; } + if (r != rem) + goto fail; + hash->write (context, readbuf, rem); + keyid = grub_subpacket_keyid_search (readbuf, rem); + grub_free (readbuf); + hash->write (context, &v, sizeof (v)); s = 0xff; hash->write (context, &s, sizeof (s)); @@ -550,40 +600,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); if (r != sizeof (unhashed_sub)) goto fail; - { - grub_uint8_t *ptr; - grub_uint32_t l; - rem = grub_be_to_cpu16 (unhashed_sub); - if (rem > READBUF_SIZE) - goto fail; - r = grub_file_read (sig, readbuf, rem); - if (r != rem) - goto fail; - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) - { - if (*ptr < 192) - l = *ptr++; - else if (*ptr < 255) - { - if (ptr + 1 >= readbuf + rem) - break; - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; - ptr += 2; - } - else - { - if (ptr + 5 >= readbuf + rem) - break; - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); - ptr += 5; - } - if (*ptr == 0x10 && l >= 8) - keyid = grub_get_unaligned64 (ptr + 1); - } - } + rem = grub_be_to_cpu16 (unhashed_sub); + readbuf = grub_malloc (rem); + if (!readbuf) + goto fail; + + r = 0; + while (r < rem) + { + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); + if (rr < 0) + goto fail; + if (rr == 0) + break; + r += rr; + } + if (r != rem) + goto fail; + + if (keyid == 0) + keyid = grub_subpacket_keyid_search (readbuf, rem); + grub_free (readbuf); hash->final (context); + readbuf = grub_zalloc (READBUF_SIZE); + if (!readbuf) + goto fail; + grub_dprintf ("crypt", "alive\n"); hval = hash->read (context); -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-02 16:58 ` [PATCH v2] verify: search keyid in hashed signature subpackets Ignat Korchagin @ 2016-12-05 15:24 ` Daniel Kiper 2016-12-05 15:26 ` Ignat Korchagin 2016-12-10 17:59 ` Andrei Borzenkov 1 sibling, 1 reply; 14+ messages in thread From: Daniel Kiper @ 2016-12-05 15:24 UTC (permalink / raw) To: Ignat Korchagin; +Cc: grub-devel, Daniel Kiper On Fri, Dec 02, 2016 at 04:58:39PM +0000, Ignat Korchagin wrote: > According to RFC 4880 5.2.3 only "Signature Creation Time" subpacket > "MUST" be present in the hashed area. All other subpacket types may be present > either in hashed or unhashed areas. Currently GRUB assumes, that the "Issuer" > subpacket is in unhashed area (by default put there by gpg tool), but other > PGP implementations (like https://godoc.org/golang.org/x/crypto/openpgp) > may put it in the hashed area. In general LGTM. One nitpick, may I add your SOB (Signed-off-by) here? Otherwise if there are no objections in 2-3 days I will apply it. Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-05 15:24 ` Daniel Kiper @ 2016-12-05 15:26 ` Ignat Korchagin 0 siblings, 0 replies; 14+ messages in thread From: Ignat Korchagin @ 2016-12-05 15:26 UTC (permalink / raw) To: Daniel Kiper; +Cc: grub-devel > One nitpick, may I add your SOB (Signed-off-by) here? Sorry, somehow I missed it this time (probably forgot to specify the git option). Yes, please add it. On Mon, Dec 5, 2016 at 3:24 PM, Daniel Kiper <dkiper@net-space.pl> wrote: > On Fri, Dec 02, 2016 at 04:58:39PM +0000, Ignat Korchagin wrote: >> According to RFC 4880 5.2.3 only "Signature Creation Time" subpacket >> "MUST" be present in the hashed area. All other subpacket types may be present >> either in hashed or unhashed areas. Currently GRUB assumes, that the "Issuer" >> subpacket is in unhashed area (by default put there by gpg tool), but other >> PGP implementations (like https://godoc.org/golang.org/x/crypto/openpgp) >> may put it in the hashed area. > > In general LGTM. One nitpick, may I add your SOB (Signed-off-by) here? > Otherwise if there are no objections in 2-3 days I will apply it. > > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-02 16:58 ` [PATCH v2] verify: search keyid in hashed signature subpackets Ignat Korchagin 2016-12-05 15:24 ` Daniel Kiper @ 2016-12-10 17:59 ` Andrei Borzenkov 2016-12-11 14:51 ` Ignat Korchagin 1 sibling, 1 reply; 14+ messages in thread From: Andrei Borzenkov @ 2016-12-10 17:59 UTC (permalink / raw) To: The development of GNU GRUB; +Cc: Daniel Kiper, Ignat Korchagin 02.12.2016 19:58, Ignat Korchagin пишет: > According to RFC 4880 5.2.3 only "Signature Creation Time" subpacket > "MUST" be present in the hashed area. All other subpacket types may be present > either in hashed or unhashed areas. Currently GRUB assumes, that the "Issuer" > subpacket is in unhashed area (by default put there by gpg tool), but other > PGP implementations (like https://godoc.org/golang.org/x/crypto/openpgp) > may put it in the hashed area. > --- > grub-core/commands/verify.c | 122 ++++++++++++++++++++++++++++++-------------- > 1 file changed, 83 insertions(+), 39 deletions(-) > > diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c > index 67cb1c7..79b3826 100644 > --- a/grub-core/commands/verify.c > +++ b/grub-core/commands/verify.c > @@ -33,6 +33,9 @@ > > GRUB_MOD_LICENSE ("GPLv3+"); > > +/* RFC 4880 5.2.3.1 */ > +#define OPENPGP_SIGNATURE_SUBPACKET_TYPE 16 > + > struct grub_verified > { > grub_file_t file; > @@ -445,6 +448,42 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, > return ret; > } > > +/* > + * Parsing algorithm from RFC 4880 5.2.3.1 > + */ > + > +static grub_uint64_t > +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) > +{ > + const grub_uint8_t *ptr; > + grub_uint32_t l; > + grub_uint64_t keyid = 0; > + > + for (ptr = sub; ptr < sub + sub_len; ptr += l) > + { > + if (*ptr < 192) > + l = *ptr++; > + else if (*ptr < 255) > + { > + if (ptr + 1 >= sub + sub_len) > + break; > + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; > + ptr += 2; > + } > + else > + { > + if (ptr + 5 >= sub + sub_len) > + break; > + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); > + ptr += 5; > + } > + if (*ptr == OPENPGP_SIGNATURE_SUBPACKET_TYPE && l >= 8) Overflow check? ptr + 8 < ptr + sub_len > + keyid = grub_get_unaligned64 (ptr + 1); > + } > + > + return keyid; > +} > + > static grub_err_t > grub_verify_signature_real (char *buf, grub_size_t size, > grub_file_t f, grub_file_t sig, > @@ -529,20 +568,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, > break; > hash->write (context, readbuf, r); > } > + grub_free (readbuf); > + > + readbuf = grub_malloc (rem); > + if (!readbuf) > + goto fail; > > hash->write (context, &v, sizeof (v)); > hash->write (context, &v4, sizeof (v4)); > - while (rem) > + > + r = 0; > + while (r < rem) > { > - r = grub_file_read (sig, readbuf, > - rem < READBUF_SIZE ? rem : READBUF_SIZE); > - if (r < 0) > - goto fail; > - if (r == 0) > + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); > + if (rr < 0) > + goto fail; > + if (rr == 0) > break; > - hash->write (context, readbuf, r); > - rem -= r; > + r += rr; > } > + if (r != rem) > + goto fail; I think this loop is overcomplicated. In all other places we assume that short read from grub_file_read means error. > + hash->write (context, readbuf, rem); > + keyid = grub_subpacket_keyid_search (readbuf, rem); > + grub_free (readbuf); > + > hash->write (context, &v, sizeof (v)); > s = 0xff; > hash->write (context, &s, sizeof (s)); > @@ -550,40 +600,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, > r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); > if (r != sizeof (unhashed_sub)) > goto fail; > - { > - grub_uint8_t *ptr; > - grub_uint32_t l; > - rem = grub_be_to_cpu16 (unhashed_sub); > - if (rem > READBUF_SIZE) > - goto fail; > - r = grub_file_read (sig, readbuf, rem); > - if (r != rem) > - goto fail; > - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) > - { > - if (*ptr < 192) > - l = *ptr++; > - else if (*ptr < 255) > - { > - if (ptr + 1 >= readbuf + rem) > - break; > - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; > - ptr += 2; > - } > - else > - { > - if (ptr + 5 >= readbuf + rem) > - break; > - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); > - ptr += 5; > - } > - if (*ptr == 0x10 && l >= 8) > - keyid = grub_get_unaligned64 (ptr + 1); > - } > - } > + rem = grub_be_to_cpu16 (unhashed_sub); > + readbuf = grub_malloc (rem); > + if (!readbuf) > + goto fail; > + > + r = 0; > + while (r < rem) > + { > + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); > + if (rr < 0) > + goto fail; > + if (rr == 0) > + break; > + r += rr; > + } > + if (r != rem) > + goto fail; > + Ditto. > + if (keyid == 0) > + keyid = grub_subpacket_keyid_search (readbuf, rem); > + grub_free (readbuf); > > hash->final (context); > > + readbuf = grub_zalloc (READBUF_SIZE); No need to use grub_zalloc here, we did not zero buffer before as well. > + if (!readbuf) > + goto fail; > + > grub_dprintf ("crypt", "alive\n"); > > hval = hash->read (context); > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-10 17:59 ` Andrei Borzenkov @ 2016-12-11 14:51 ` Ignat Korchagin 2016-12-12 13:20 ` Daniel Kiper 0 siblings, 1 reply; 14+ messages in thread From: Ignat Korchagin @ 2016-12-11 14:51 UTC (permalink / raw) To: Andrei Borzenkov; +Cc: The development of GNU GRUB, Daniel Kiper General thoughts: Just a reminder: this patch tries to fix a BUG in code, which was present from the introduction of this functionality and acknowledged for more than 9 month now. The goal of this patch is to fix it without introducing too much change. We are spending too much time "improving" things and forgetting that basic functionality is broken. Probably, most of us have experience working in software companies and the basic flow of any software development is: - fix bugs - improve - goto step 1; So fixing bugs and improvements should be in separate steps. I do not think it is an excuse not to fix bugs for 9 month in the hope of improving code readability along the way. That should be a separate task. Unfortunately, I do not have time to continuously rebase the PR for each 1 month delay - GRUB is not my primary and even second responsibility at work. I'm just trying to be nice and contribute back what I found broken. But I'm just a regular user and I have to cut this time from my family to do this. Actually, IMHO, this whole file needs to be redone, so comments regarding "this or that unclear" applies to everything there. As I said multiple times, I almost did not introduce new code, but just refactored the existing one fix the issue. I'm not aware of any decisions made prior to this patch. Many times in this mailing list there were requests to be considerate that GRUB maintainers are very busy and cannot always act/respond quickly. But, guess what: this goes the other way around - GRUB contributors can be busy as well. If you make me rebase the patch each month with new not very relevant comments I will give up essentially. If you think the code needs improvements, you are free to ask me for a follow-up with general directions/requirements for what you think is wrong. But, please, make a little effort to fix the work already done. The patch is not that big, but to prepare it I had to spend time to read and understand the whole PGP RFC (and their data formats and encodings are not that simple I would say). And after 9 month I do not even remember the specifics. General thoughts on improving GRUB development: - let's be tolerant to each other - for God's sake, let's move to a modern code hosting with convenient modern workflows (PRs, reviews etc). Yes, previously you said that you want to be able to review patches on the phone, but I do not imagine you guys having not being able to do this with a reasonable smartphone. Because fighting with git send-mail and subverting my email 2-factor auth just to send a patch makes me (and probably many others) very sad (and insecure BTW) - there should be no comments, like (taken from real-life) "I do not think this is a right name for this function". The right form would be "I do not think this is a right name for this function, how about <PUT YOUR PROPOSAL HERE>". We are not mind-readers and do not have full visibility into GRUB project. - ... Sorry for the noise, but this is something which came up working on this... Specific patch comments below. On Sat, Dec 10, 2016 at 5:59 PM, Andrei Borzenkov <arvidjaar@gmail.com> wrote: > 02.12.2016 19:58, Ignat Korchagin пишет: >> According to RFC 4880 5.2.3 only "Signature Creation Time" subpacket >> "MUST" be present in the hashed area. All other subpacket types may be present >> either in hashed or unhashed areas. Currently GRUB assumes, that the "Issuer" >> subpacket is in unhashed area (by default put there by gpg tool), but other >> PGP implementations (like https://godoc.org/golang.org/x/crypto/openpgp) >> may put it in the hashed area. >> --- >> grub-core/commands/verify.c | 122 ++++++++++++++++++++++++++++++-------------- >> 1 file changed, 83 insertions(+), 39 deletions(-) >> >> diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c >> index 67cb1c7..79b3826 100644 >> --- a/grub-core/commands/verify.c >> +++ b/grub-core/commands/verify.c >> @@ -33,6 +33,9 @@ >> >> GRUB_MOD_LICENSE ("GPLv3+"); >> >> +/* RFC 4880 5.2.3.1 */ >> +#define OPENPGP_SIGNATURE_SUBPACKET_TYPE 16 >> + >> struct grub_verified >> { >> grub_file_t file; >> @@ -445,6 +448,42 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, >> return ret; >> } >> >> +/* >> + * Parsing algorithm from RFC 4880 5.2.3.1 >> + */ >> + >> +static grub_uint64_t >> +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) >> +{ >> + const grub_uint8_t *ptr; >> + grub_uint32_t l; >> + grub_uint64_t keyid = 0; >> + >> + for (ptr = sub; ptr < sub + sub_len; ptr += l) >> + { >> + if (*ptr < 192) >> + l = *ptr++; >> + else if (*ptr < 255) >> + { >> + if (ptr + 1 >= sub + sub_len) >> + break; >> + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; >> + ptr += 2; >> + } >> + else >> + { >> + if (ptr + 5 >= sub + sub_len) >> + break; >> + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); >> + ptr += 5; >> + } >> + if (*ptr == OPENPGP_SIGNATURE_SUBPACKET_TYPE && l >= 8) > > Overflow check? ptr + 8 < ptr + sub_len This and more: this specific packet can be in the middle of "packet collection", but its length should be >=8. We do not want to potentially read data from subsequent packets (no overflow, but getting invalid data). >> + keyid = grub_get_unaligned64 (ptr + 1); >> + } >> + >> + return keyid; >> +} >> + >> static grub_err_t >> grub_verify_signature_real (char *buf, grub_size_t size, >> grub_file_t f, grub_file_t sig, >> @@ -529,20 +568,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, >> break; >> hash->write (context, readbuf, r); >> } >> + grub_free (readbuf); >> + >> + readbuf = grub_malloc (rem); >> + if (!readbuf) >> + goto fail; >> >> hash->write (context, &v, sizeof (v)); >> hash->write (context, &v4, sizeof (v4)); >> - while (rem) >> + >> + r = 0; >> + while (r < rem) >> { >> - r = grub_file_read (sig, readbuf, >> - rem < READBUF_SIZE ? rem : READBUF_SIZE); >> - if (r < 0) >> - goto fail; >> - if (r == 0) >> + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); >> + if (rr < 0) >> + goto fail; >> + if (rr == 0) >> break; >> - hash->write (context, readbuf, r); >> - rem -= r; >> + r += rr; >> } >> + if (r != rem) >> + goto fail; > > I think this loop is overcomplicated. In all other places we assume that > short read from grub_file_read means error. > I remember I had justification for it, but do not remember what it is, because I wrote this 9 month ago. >> + hash->write (context, readbuf, rem); >> + keyid = grub_subpacket_keyid_search (readbuf, rem); >> + grub_free (readbuf); >> + >> hash->write (context, &v, sizeof (v)); >> s = 0xff; >> hash->write (context, &s, sizeof (s)); >> @@ -550,40 +600,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, >> r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); >> if (r != sizeof (unhashed_sub)) >> goto fail; >> - { >> - grub_uint8_t *ptr; >> - grub_uint32_t l; >> - rem = grub_be_to_cpu16 (unhashed_sub); >> - if (rem > READBUF_SIZE) >> - goto fail; >> - r = grub_file_read (sig, readbuf, rem); >> - if (r != rem) >> - goto fail; >> - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) >> - { >> - if (*ptr < 192) >> - l = *ptr++; >> - else if (*ptr < 255) >> - { >> - if (ptr + 1 >= readbuf + rem) >> - break; >> - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; >> - ptr += 2; >> - } >> - else >> - { >> - if (ptr + 5 >= readbuf + rem) >> - break; >> - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); >> - ptr += 5; >> - } >> - if (*ptr == 0x10 && l >= 8) >> - keyid = grub_get_unaligned64 (ptr + 1); >> - } >> - } >> + rem = grub_be_to_cpu16 (unhashed_sub); >> + readbuf = grub_malloc (rem); >> + if (!readbuf) >> + goto fail; >> + >> + r = 0; >> + while (r < rem) >> + { >> + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); >> + if (rr < 0) >> + goto fail; >> + if (rr == 0) >> + break; >> + r += rr; >> + } >> + if (r != rem) >> + goto fail; >> + > > Ditto. > Ditto. >> + if (keyid == 0) >> + keyid = grub_subpacket_keyid_search (readbuf, rem); >> + grub_free (readbuf); >> >> hash->final (context); >> >> + readbuf = grub_zalloc (READBUF_SIZE); > > No need to use grub_zalloc here, we did not zero buffer before as well. > We agreed previously that we should keep "what is correct" (your comment from 30 March 2016). Currently the function allocates the buffer with grub_zalloc (READBUF_SIZE). I changed buffer allocation for my code, but I have no idea about the assumptions of the code which follows. So, if previously, that code used buffer allocalted with grub_zalloc I do the same for compatibility. >> + if (!readbuf) >> + goto fail; >> + >> grub_dprintf ("crypt", "alive\n"); >> >> hval = hash->read (context); >> > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-11 14:51 ` Ignat Korchagin @ 2016-12-12 13:20 ` Daniel Kiper 2016-12-15 17:30 ` Ignat Korchagin 0 siblings, 1 reply; 14+ messages in thread From: Daniel Kiper @ 2016-12-12 13:20 UTC (permalink / raw) To: Ignat Korchagin Cc: Andrei Borzenkov, The development of GNU GRUB, Daniel Kiper Hi Ignat, On Sun, Dec 11, 2016 at 02:51:00PM +0000, Ignat Korchagin wrote: > General thoughts: > Just a reminder: this patch tries to fix a BUG in code, which was > present from the introduction of this functionality and acknowledged > for more than 9 month now. The goal of this patch is to fix it without > introducing too much change. We are spending too much time "improving" > things and forgetting that basic functionality is broken. [...] Thank you for your work. I understand your POV but I think that Andrei's questions are valid too. I know that this sounds stupid but please be patient. We are trying to rectify all GRUB2 maintenance issues. Unfortunately it takes time especially if backlog is huge. Personally I can promise that I will do my best to get your fixes into 2.02 release. However, we need your support and a bit of understanding too. Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] verify: search keyid in hashed signature subpackets 2016-12-12 13:20 ` Daniel Kiper @ 2016-12-15 17:30 ` Ignat Korchagin 0 siblings, 0 replies; 14+ messages in thread From: Ignat Korchagin @ 2016-12-15 17:30 UTC (permalink / raw) To: Daniel Kiper; +Cc: Andrei Borzenkov, The development of GNU GRUB [-- Attachment #1: Type: text/plain, Size: 1976 bytes --] Hi, > please be patient I'm not in a hurry. Like probably everyone else I have a fork repo where all changes are present. Just wanted to rely more on upstream in the future > Unfortunately it takes time especially if backlog is huge That is my point: if environment is more friendly, probably you would get more help in working through backlog But, anyway, back to the patch: I recovered some of the context of my code, so here are the details > I think this loop is overcomplicated. In all other places we assume that > short read from grub_file_read means error. This loop validates incorrect (or even bogus) signature format. The format should be (simplified) |total len|subpack1|subpack2|.... Each subpacket has its own length specified as well This loop tries to verify that the overall processed packet length match. Since we we process arbitrary length here, I do not see a better approach As for other concerns I commented in my previous reply to the patch. Thank you. On Mon, Dec 12, 2016 at 1:20 PM, Daniel Kiper <dkiper@net-space.pl> wrote: > Hi Ignat, > > On Sun, Dec 11, 2016 at 02:51:00PM +0000, Ignat Korchagin wrote: > > General thoughts: > > Just a reminder: this patch tries to fix a BUG in code, which was > > present from the introduction of this functionality and acknowledged > > for more than 9 month now. The goal of this patch is to fix it without > > introducing too much change. We are spending too much time "improving" > > things and forgetting that basic functionality is broken. > > [...] > > Thank you for your work. I understand your POV but I think that Andrei's > questions > are valid too. I know that this sounds stupid but please be patient. We > are trying > to rectify all GRUB2 maintenance issues. Unfortunately it takes time > especially if > backlog is huge. Personally I can promise that I will do my best to get > your fixes > into 2.02 release. However, we need your support and a bit of > understanding too. > > Daniel > [-- Attachment #2: Type: text/html, Size: 3786 bytes --] ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-21 14:45 ` Daniel Kiper 2016-11-21 17:56 ` Jon McCune @ 2016-11-21 22:25 ` Ignat Korchagin 2016-11-22 8:26 ` Daniel Kiper 1 sibling, 1 reply; 14+ messages in thread From: Ignat Korchagin @ 2016-11-21 22:25 UTC (permalink / raw) To: Daniel Kiper; +Cc: The development of GNU GRUB, Andrei Borzenkov On Mon, Nov 21, 2016 at 3:45 PM, Daniel Kiper <dkiper@net-space.pl> wrote: > On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: >> Reposting this, as requested by Daniel and rebasing on current tree. >> >> Currently GRUB2 verify logic searches PGP keyid only in unhashed subpackets of PGP signature packet. As a result, signatures generated with GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could not be verified, because this package puts keyid in hashed subpackets and GRUB code never initializes the keyid variable, therefore is not able to find "verification key" with id 0x0. >> >> Signed-off-by: Ignat Korchagin <ignat@cloudflare.com> >> --- >> grub-core/commands/verify.c | 115 +++++++++++++++++++++++++++++--------------- >> 1 file changed, 76 insertions(+), 39 deletions(-) >> >> diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c >> index 67cb1c7..1b628b2 100644 >> --- a/grub-core/commands/verify.c >> +++ b/grub-core/commands/verify.c >> @@ -445,6 +445,38 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, >> return ret; >> } >> >> +static grub_uint64_t >> +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) >> +{ >> + const grub_uint8_t *ptr; >> + grub_uint32_t l; >> + grub_uint64_t keyid = 0; >> + >> + for (ptr = sub; ptr < sub + sub_len; ptr += l) >> + { >> + if (*ptr < 192) > > Please define some constants and use them properly... This is original GRUB code here. It was just moved to a separate function. See below. Also, defining constants here is probably more confusing. I do not know for sure, but suspect this algorithm is taken directly from RFC 4880 5.2.3.1 and there are no names there > >> + l = *ptr++; >> + else if (*ptr < 255) > > Ditto. > >> + { >> + if (ptr + 1 >= sub + sub_len) >> + break; >> + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; > > Ditto. > >> + ptr += 2; > > Ditto and below... > >> + } >> + else >> + { >> + if (ptr + 5 >= sub + sub_len) >> + break; >> + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); >> + ptr += 5; >> + } >> + if (*ptr == 0x10 && l >= 8) >> + keyid = grub_get_unaligned64 (ptr + 1); >> + } >> + >> + return keyid; >> +} >> + >> static grub_err_t >> grub_verify_signature_real (char *buf, grub_size_t size, >> grub_file_t f, grub_file_t sig, >> @@ -529,20 +561,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, >> break; >> hash->write (context, readbuf, r); >> } >> + grub_free (readbuf); >> + >> + readbuf = grub_malloc (rem); > > grub_zalloc()? This buffer is filled below by grub_file_read, so no need to waste cycles zeroing it. > >> + if (!readbuf) >> + goto fail; >> >> hash->write (context, &v, sizeof (v)); >> hash->write (context, &v4, sizeof (v4)); >> - while (rem) >> + >> + r = 0; >> + while (r < rem) >> { >> - r = grub_file_read (sig, readbuf, >> - rem < READBUF_SIZE ? rem : READBUF_SIZE); >> - if (r < 0) >> - goto fail; >> - if (r == 0) >> + grub_ssize_t rr = grub_file_read (sig, readbuf + r, rem - r); >> + if (rr < 0) >> + goto fail; >> + if (rr == 0) >> break; >> - hash->write (context, readbuf, r); >> - rem -= r; >> + r += rr; >> } >> + if (r != rem) >> + goto fail; >> + hash->write (context, readbuf, rem); >> + keyid = grub_subpacket_keyid_search (readbuf, rem); >> + grub_free (readbuf); >> + >> hash->write (context, &v, sizeof (v)); >> s = 0xff; >> hash->write (context, &s, sizeof (s)); >> @@ -550,40 +593,34 @@ grub_verify_signature_real (char *buf, grub_size_t size, >> r = grub_file_read (sig, &unhashed_sub, sizeof (unhashed_sub)); >> if (r != sizeof (unhashed_sub)) >> goto fail; >> - { >> - grub_uint8_t *ptr; >> - grub_uint32_t l; >> - rem = grub_be_to_cpu16 (unhashed_sub); >> - if (rem > READBUF_SIZE) >> - goto fail; >> - r = grub_file_read (sig, readbuf, rem); >> - if (r != rem) >> - goto fail; >> - for (ptr = readbuf; ptr < readbuf + rem; ptr += l) >> - { >> - if (*ptr < 192) >> - l = *ptr++; >> - else if (*ptr < 255) >> - { >> - if (ptr + 1 >= readbuf + rem) >> - break; >> - l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; >> - ptr += 2; >> - } >> - else >> - { >> - if (ptr + 5 >= readbuf + rem) >> - break; >> - l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); >> - ptr += 5; >> - } >> - if (*ptr == 0x10 && l >= 8) >> - keyid = grub_get_unaligned64 (ptr + 1); >> - } >> - } >> + rem = grub_be_to_cpu16 (unhashed_sub); >> + readbuf = grub_malloc (rem); > > grub_zalloc()? Same as above > > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] verify: search keyid in hashed signature subpackets (repost) 2016-11-21 22:25 ` [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin @ 2016-11-22 8:26 ` Daniel Kiper 0 siblings, 0 replies; 14+ messages in thread From: Daniel Kiper @ 2016-11-22 8:26 UTC (permalink / raw) To: ignat, grub-devel; +Cc: dkiper, arvidjaar On Mon, Nov 21, 2016 at 11:25:30PM +0100, Ignat Korchagin wrote: > On Mon, Nov 21, 2016 at 3:45 PM, Daniel Kiper <dkiper@net-space.pl> wrote: > > On Fri, Nov 18, 2016 at 12:00:08PM +0000, Ignat Korchagin wrote: > >> Reposting this, as requested by Daniel and rebasing on current tree. > >> > >> Currently GRUB2 verify logic searches PGP keyid only in unhashed subpackets of PGP signature packet. As a result, signatures generated with GoLang openpgp package (https://godoc.org/golang.org/x/crypto/openpgp) could not be verified, because this package puts keyid in hashed subpackets and GRUB code never initializes the keyid variable, therefore is not able to find "verification key" with id 0x0. > >> > >> Signed-off-by: Ignat Korchagin <ignat@cloudflare.com> > >> --- > >> grub-core/commands/verify.c | 115 +++++++++++++++++++++++++++++--------------- > >> 1 file changed, 76 insertions(+), 39 deletions(-) > >> > >> diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c > >> index 67cb1c7..1b628b2 100644 > >> --- a/grub-core/commands/verify.c > >> +++ b/grub-core/commands/verify.c > >> @@ -445,6 +445,38 @@ rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, > >> return ret; > >> } > >> > >> +static grub_uint64_t > >> +grub_subpacket_keyid_search (const grub_uint8_t * sub, grub_ssize_t sub_len) > >> +{ > >> + const grub_uint8_t *ptr; > >> + grub_uint32_t l; > >> + grub_uint64_t keyid = 0; > >> + > >> + for (ptr = sub; ptr < sub + sub_len; ptr += l) > >> + { > >> + if (*ptr < 192) > > > > Please define some constants and use them properly... > This is original GRUB code here. It was just moved to a separate > function. See below. OK, however, I am against leaving unreadable code if we touch it anyway. > Also, defining constants here is probably more confusing. > I do not know for sure, but suspect this algorithm is taken directly > from RFC 4880 5.2.3.1 and there are no names there So, say this thing in comment before grub_subpacket_keyid_search() function. This will improve situation a bit. > >> + l = *ptr++; > >> + else if (*ptr < 255) > > > > Ditto. > > > >> + { > >> + if (ptr + 1 >= sub + sub_len) > >> + break; > >> + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; > > > > Ditto. > > > >> + ptr += 2; > > > > Ditto and below... > > > >> + } > >> + else > >> + { > >> + if (ptr + 5 >= sub + sub_len) > >> + break; > >> + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); > >> + ptr += 5; > >> + } > >> + if (*ptr == 0x10 && l >= 8) > >> + keyid = grub_get_unaligned64 (ptr + 1); > >> + } > >> + > >> + return keyid; > >> +} > >> + > >> static grub_err_t > >> grub_verify_signature_real (char *buf, grub_size_t size, > >> grub_file_t f, grub_file_t sig, > >> @@ -529,20 +561,31 @@ grub_verify_signature_real (char *buf, grub_size_t size, > >> break; > >> hash->write (context, readbuf, r); > >> } > >> + grub_free (readbuf); > >> + > >> + readbuf = grub_malloc (rem); > > > > grub_zalloc()? > This buffer is filled below by grub_file_read, so no need to waste > cycles zeroing it. Right, I realized that after posting my email. Hence, let's leave grub_malloc() as is here and below. Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2016-12-15 17:32 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-11-18 12:00 [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin 2016-11-21 14:45 ` Daniel Kiper 2016-11-21 17:56 ` Jon McCune 2016-11-21 22:31 ` Ignat Korchagin 2016-11-22 8:28 ` Daniel Kiper 2016-12-02 16:58 ` [PATCH v2] verify: search keyid in hashed signature subpackets Ignat Korchagin 2016-12-05 15:24 ` Daniel Kiper 2016-12-05 15:26 ` Ignat Korchagin 2016-12-10 17:59 ` Andrei Borzenkov 2016-12-11 14:51 ` Ignat Korchagin 2016-12-12 13:20 ` Daniel Kiper 2016-12-15 17:30 ` Ignat Korchagin 2016-11-21 22:25 ` [PATCH] verify: search keyid in hashed signature subpackets (repost) Ignat Korchagin 2016-11-22 8:26 ` Daniel Kiper
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).