From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1cCrDi-0006HY-FQ for mharc-grub-devel@gnu.org; Fri, 02 Dec 2016 12:01:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50547) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cCrDf-0006Eq-S4 for grub-devel@gnu.org; Fri, 02 Dec 2016 12:01:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cCrDb-0005Mz-Ks for grub-devel@gnu.org; Fri, 02 Dec 2016 12:01:55 -0500 Received: from mail-wm0-x22d.google.com ([2a00:1450:400c:c09::22d]:36158) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cCrDb-0005Mh-B9 for grub-devel@gnu.org; Fri, 02 Dec 2016 12:01:51 -0500 Received: by mail-wm0-x22d.google.com with SMTP id g23so22777868wme.1 for ; Fri, 02 Dec 2016 09:01:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to; bh=/dNF8+/V3swjtJVLtG1/oW7KIhVmaPSrH5YMJ+sxwto=; b=Jb0G3sYWE4nD7+p5TNd4IAa1ewiJkPk23Pa3Qn0zQIfrCsxoyU419evvINW8UU6W4J bUyqzbH5q7obSAvrswYE9JYm9fOQg60172E/WMrJ3oV4AWMIK04+kunY+fz/JC1BZcyH vqwXS571Iy8Sey7za/a76fLxk2GNxl18Sv5S0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to; bh=/dNF8+/V3swjtJVLtG1/oW7KIhVmaPSrH5YMJ+sxwto=; b=aS5jSmkQSY5QG5fSTgjVJQyozyy9rUUirAAhGEwPAA3xK2Am52rBDANVv6bGFBUsWi TcEI1qFcqV+ZAwniIow5+0R4YrvR3NrrVMSWhlt5M7yJMPZBs0WPWNnVidI574K2xvUB u7F4cyAFIEYTl28Tl7ZpZiKz8Fi3HicExO1JtlUuYZJ0hwzr0mccuKCtC2n0vbf4f5i4 I4IwTemLEpzMRDN4VLAGRDs2p8kS6FDUjTOXCAKaLh4QG2I0/OFXy43zbJvSJw6O8Sg3 WRd4HtATlDD8feVzHh8iuNj7nCuPZpEKpfk4rcd7yOkMIn+Fi7IurDyNMQVenrPLBSL4 wjWw== X-Gm-Message-State: AKaTC01hmka1mFTOh7V2h9LdnRTJC2hjEOjcseHVhuddd9YxEa63OwiX1HKm4nJStgm0IpaR X-Received: by 10.28.49.3 with SMTP id x3mr3858479wmx.121.1480698108602; Fri, 02 Dec 2016 09:01:48 -0800 (PST) Received: from debmicro.secboot ([185.122.0.240]) by smtp.gmail.com with ESMTPSA id f76sm4124794wmd.15.2016.12.02.09.01.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 02 Dec 2016 09:01:48 -0800 (PST) From: Ignat Korchagin To: grub-devel Cc: Ignat Korchagin , Daniel Kiper Subject: [PATCH v2] verify: search keyid in hashed signature subpackets Date: Fri, 2 Dec 2016 16:58:39 +0000 Message-Id: <1480697919-23371-1-git-send-email-ignat@cloudflare.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <20161122082806.GB4706@router-fw-old.local.net-space.pl> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::22d X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 02 Dec 2016 17:01:57 -0000 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