From 949bebfc81c70def24efcdcb586fc943c03d9834 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Wed, 14 Sep 2022 20:41:01 +0530 Subject: [PATCH] rpm: further fixes to CVE-2021-3521 - CVE-2021-3521.patch taken from https://git.rockylinux.org/staging/rpms/rpm/-/blob/r8/SOURCES/rpm-4.14.3-validate-and-require-subkey-binding-sigs.patch - And add rpm upstream commit https://github.com/rpm-software-management/rpm/commit/daeddb01de50c53b98eae75e11234132ae63538a This is based on suggestion https://github.com/rpm-software-management/rpm/pull/1795#issuecomment-1246543099 Change-Id: Ie6222da4f001e36f4584844c83946dbec72bf283 Signed-off-by: Shreenidhi Shedi Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/17876 Reviewed-by: Tapas Kundu Tested-by: Tapas Kundu --- SPECS/rpm/CVE-2021-3521-1.patch | 62 ---- SPECS/rpm/CVE-2021-3521-2.patch | 52 ---- ...-2021-3521-3.patch => CVE-2021-3521.patch} | 203 +++++++++++-- SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch | 286 ------------------ SPECS/rpm/rpm.spec | 16 +- 5 files changed, 183 insertions(+), 436 deletions(-) delete mode 100644 SPECS/rpm/CVE-2021-3521-1.patch delete mode 100644 SPECS/rpm/CVE-2021-3521-2.patch rename SPECS/rpm/{CVE-2021-3521-3.patch => CVE-2021-3521.patch} (64%) delete mode 100644 SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch diff --git a/SPECS/rpm/CVE-2021-3521-1.patch b/SPECS/rpm/CVE-2021-3521-1.patch deleted file mode 100644 index abb372bab0..0000000000 --- a/SPECS/rpm/CVE-2021-3521-1.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 268f7345643052dc899f2d363b24d91c10450dfc Mon Sep 17 00:00:00 2001 -From: Panu Matilainen -Date: Thu, 30 Sep 2021 09:51:10 +0300 -Subject: [PATCH 1/3] Process MPI's from all kinds of signatures - -No immediate effect but needed by the following commits. - -[sshedi: back port to v4.14.3] - -Signed-off-by: Shreenidhi Shedi ---- - rpmio/rpmpgp.c | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index c71503b..77c6d97 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -539,7 +539,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg) - return NULL; - } - --static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, -+static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, - const uint8_t *p, const uint8_t *h, size_t hlen, - pgpDigParams sigp) - { -@@ -552,10 +552,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - int mpil = pgpMpiLen(p); - if (mpil > pend - p) - break; -- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { -- if (sigalg->setmpi(sigalg, i, p)) -- break; -- } -+ if (sigalg->setmpi(sigalg, i, p)) -+ break; - p += mpil; - } - -@@ -615,7 +613,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - } - - p = ((uint8_t *)v) + sizeof(*v); -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); - } break; - case 4: - { pgpPktSigV4 v = (pgpPktSigV4)h; -@@ -664,8 +662,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - memcpy(_digp->signhash16, p, sizeof(_digp->signhash16)); - } - -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p + 2, h, hlen, -- _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, p + 2, h, hlen, _digp); - } break; - default: - rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); --- -2.25.1 - diff --git a/SPECS/rpm/CVE-2021-3521-2.patch b/SPECS/rpm/CVE-2021-3521-2.patch deleted file mode 100644 index d62003f9fd..0000000000 --- a/SPECS/rpm/CVE-2021-3521-2.patch +++ /dev/null @@ -1,52 +0,0 @@ -From f1f4e643a372309b43600e4941bec6a6de3d9d63 Mon Sep 17 00:00:00 2001 -From: Panu Matilainen -Date: Thu, 30 Sep 2021 09:56:20 +0300 -Subject: [PATCH 2/3] Refactor pgpDigParams construction to helper function - -No functional changes, just to reduce code duplication and needed by -the following commits. ---- - rpmio/rpmpgp.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 77c6d97..8f48509 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -1010,6 +1010,13 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype) - return algo; - } - -+static pgpDigParams pgpDigParamsNew(uint8_t tag) -+{ -+ pgpDigParams digp = xcalloc(1, sizeof(*digp)); -+ digp->tag = tag; -+ return digp; -+} -+ - int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - pgpDigParams * ret) - { -@@ -1027,8 +1034,7 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - if (pkttype && pkt.tag != pkttype) { - break; - } else { -- digp = xcalloc(1, sizeof(*digp)); -- digp->tag = pkt.tag; -+ digp = pgpDigParamsNew(pkt.tag); - } - } - -@@ -1076,8 +1082,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, - digps = xrealloc(digps, alloced * sizeof(*digps)); - } - -- digps[count] = xcalloc(1, sizeof(**digps)); -- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; -+ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY); - /* Copy UID from main key to subkey */ - digps[count]->userid = xstrdup(mainkey->userid); - --- -2.25.1 - diff --git a/SPECS/rpm/CVE-2021-3521-3.patch b/SPECS/rpm/CVE-2021-3521.patch similarity index 64% rename from SPECS/rpm/CVE-2021-3521-3.patch rename to SPECS/rpm/CVE-2021-3521.patch index cdaed82f2b..8bfaccf45f 100644 --- a/SPECS/rpm/CVE-2021-3521-3.patch +++ b/SPECS/rpm/CVE-2021-3521.patch @@ -1,7 +1,7 @@ -From e6eb466291a07c22db2549f65295506866aa0616 Mon Sep 17 00:00:00 2001 -From: Panu Matilainen -Date: Thu, 30 Sep 2021 09:59:30 +0300 -Subject: [PATCH 3/3] Validate and require subkey binding signatures on PGP +From 747fbc8734b9016b1ba6a3123af02fdefa0832cc Mon Sep 17 00:00:00 2001 +From: Demi Marie Obenour +Date: Thu, 6 May 2021 18:34:45 -0400 +Subject: [PATCH 1/2] Validate and require subkey binding signatures on PGP public keys All subkeys must be followed by a binding signature by the primary key @@ -14,35 +14,82 @@ to be able to access previous elements at will, needed to validate ordering and access the actual data. Add testcases for manipulated keys whose import previously would succeed. -Depends on the two previous commits: -7b399fcb8f52566e6f3b4327197a85facd08db91 and -236b802a4aa48711823a191d1b7f753c82a89ec5 +Combined with: +5ff86764b17f31535cb247543a90dd739076ec38 +b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 +9f03f42e2614a68f589f9db8fe76287146522c0c +b6dffb6dc5ffa2ddc389743f0507876cab341315 (mem-leak fix) +ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 (use-after-free fix) Fixes CVE-2021-3521. - -[sshedi: back port to v4.14.3] - -Signed-off-by: Shreenidhi Shedi --- - rpmio/rpmpgp.c | 102 ++++++++++++++++-- + rpmio/rpmpgp.c | 122 +++++++++++++++--- + sign/rpmgensig.c | 2 +- tests/Makefile.am | 3 + - tests/data/keys/CVE-2021-3521-badbind.asc | 25 +++++ - .../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 +++++ - tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 +++++++ - tests/rpmsigdig.at | 28 +++++ - 6 files changed, 211 insertions(+), 9 deletions(-) + tests/data/keys/CVE-2021-3521-badbind.asc | 25 ++++ + .../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 ++++ + tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 ++++++ + tests/rpmsigdig.at | 28 ++++ + 7 files changed, 224 insertions(+), 18 deletions(-) create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 8f48509..ccc4151 100644 +index 9bd7512..e29f3fe 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c -@@ -1017,37 +1017,121 @@ static pgpDigParams pgpDigParamsNew(uint8_t tag) - return digp; +@@ -542,7 +542,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg) + return NULL; + } + +-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, ++static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, + const uint8_t *p, const uint8_t *h, size_t hlen, + pgpDigParams sigp) + { +@@ -555,10 +555,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, + int mpil = pgpMpiLen(p); + if (p + mpil > pend) + break; +- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { +- if (sigalg->setmpi(sigalg, i, p)) +- break; +- } ++ if (sigalg->setmpi(sigalg, i, p)) ++ break; + p += mpil; + } + +@@ -618,7 +616,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + } + + p = ((uint8_t *)v) + sizeof(*v); +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + case 4: + { pgpPktSigV4 v = (pgpPktSigV4)h; +@@ -676,7 +674,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + if (p > (h + hlen)) + return 1; + +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + default: + rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); +@@ -1017,36 +1015,127 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype) + return algo; } ++static pgpDigParams pgpDigParamsNew(uint8_t tag) ++{ ++ pgpDigParams digp = xcalloc(1, sizeof(*digp)); ++ digp->tag = tag; ++ return digp; ++} ++ +static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag) +{ + int rc = -1; @@ -115,7 +162,8 @@ index 8f48509..ccc4151 100644 + if (pkttype && pkt->tag != pkttype) { break; } else { -- digp = pgpDigParamsNew(pkt.tag); +- digp = xcalloc(1, sizeof(*digp)); +- digp->tag = pkt.tag; + digp = pgpDigParamsNew(pkt->tag); } } @@ -131,8 +179,6 @@ index 8f48509..ccc4151 100644 break; - p += (pkt.body - pkt.head) + pkt.blen; -- if (pkttype == PGPTAG_SIGNATURE) -- break; + if (selfsig) { + /* subkeys must be followed by binding signature */ + int xx = 1; /* assume failure */ @@ -166,24 +212,46 @@ index 8f48509..ccc4151 100644 + rc = (digp && (p == pend) && expect == 0) ? 0 : -1; + free(all); -+ selfsig = pgpDigParamsFree(selfsig); if (ret && rc == 0) { *ret = digp; } else { +@@ -1081,8 +1170,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + digps = xrealloc(digps, alloced * sizeof(*digps)); + } + +- digps[count] = xcalloc(1, sizeof(**digps)); +- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; ++ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY); + /* Copy UID from main key to subkey */ + digps[count]->userid = xstrdup(mainkey->userid); + +diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c +index 771d010..b33fe99 100644 +--- a/sign/rpmgensig.c ++++ b/sign/rpmgensig.c +@@ -409,7 +409,7 @@ static int haveSignature(rpmtd sigtd, Header h) + pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2); + if (pgpDigParamsCmp(sig1, sig2) == 0) + rc = 1; +- pgpDigParamsFree(sig2); ++ sig2 = pgpDigParamsFree(sig2); + } + pgpDigParamsFree(sig1); + rpmtdFreeData(&oldtd); diff --git a/tests/Makefile.am b/tests/Makefile.am -index 5f5207e..ea81ec4 100644 +index 5f5207e..3093472 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am -@@ -88,6 +88,9 @@ EXTRA_DIST += data/SPECS/hello-cd.spec +@@ -87,6 +87,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec + EXTRA_DIST += data/SPECS/hello-cd.spec EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.pub EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.secret - EXTRA_DIST += data/macros.testfile +EXTRA_DIST += data/keys/CVE-2021-3521-badbind.asc +EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig.asc +EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig-last.asc + EXTRA_DIST += data/macros.testfile # testsuite voodoo - AUTOTEST = $(AUTOM4TE) --language=autotest diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc new file mode 100644 index 0000000..aea00f9 @@ -331,3 +399,82 @@ index 09fcdd5..a74f400 100644 -- 2.25.1 +From 533bcf52b8c00e9281de60e1ac50c50aa9115808 Mon Sep 17 00:00:00 2001 +From: Demi Marie Obenour +Date: Thu, 6 May 2021 20:03:10 -0400 +Subject: [PATCH 2/2] verifySignature(): package signatures must be + PGPSIGTYPE_BINARY + +RPM packages are binary documents and must be signed as such. To avoid +having to access the fields of pgpDigParams() directly, this adds a new +accessor function, pgpSignatureType(). pgpSignatureType() returns the +type of a signature, or -1 if the PGP data is NULL or is not a +signature. + +Prior to commit b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 this was kind +of checked inside the parser but incorrectly. +--- + lib/rpmvs.c | 4 +++- + rpmio/rpmpgp.c | 10 ++++++++++ + rpmio/rpmpgp.h | 9 +++++++++ + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index 622e480..70f8e35 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -530,7 +530,9 @@ exit: + static rpmRC + verifySignature(rpmKeyring keyring, struct rpmsinfo_s *sinfo) + { +- rpmRC res = rpmKeyringVerifySig(keyring, sinfo->sig, sinfo->ctx); ++ rpmRC res = RPMRC_FAIL; ++ if (pgpSignatureType(sinfo->sig) == PGPSIGTYPE_BINARY) ++ res = rpmKeyringVerifySig(keyring, sinfo->sig, sinfo->ctx); + + return res; + } +diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c +index e29f3fe..1ed982b 100644 +--- a/rpmio/rpmpgp.c ++++ b/rpmio/rpmpgp.c +@@ -437,6 +437,16 @@ static int pgpVersion(const uint8_t *h, size_t hlen, uint8_t *version) + return 0; + } + ++int pgpSignatureType(pgpDigParams _digp) ++{ ++ int rc = -1; ++ ++ if (_digp && _digp->tag == PGPTAG_SIGNATURE) ++ rc = _digp->sigtype; ++ ++ return rc; ++} ++ + static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype, + pgpDigParams _digp) + { +diff --git a/rpmio/rpmpgp.h b/rpmio/rpmpgp.h +index d37a2e9..c360c23 100644 +--- a/rpmio/rpmpgp.h ++++ b/rpmio/rpmpgp.h +@@ -1133,6 +1133,15 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx) + */ + rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx); + ++/** \ingroup rpmpgp ++ * Return the type of a PGP signature. If `sig` is NULL, or is not a signature, ++ * returns -1. ++ * ++ * @param sig signature ++ * @return type of the signature ++ */ ++int pgpSignatureType(pgpDigParams sig); ++ + /** \ingroup rpmpgp + * Return a string identification of a PGP signature/pubkey. + * @param digp signature/pubkey container +-- +2.25.1 + diff --git a/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch b/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch deleted file mode 100644 index 6bd42761dc..0000000000 --- a/SPECS/rpm/Fix-OpenPGP-parsing-bugs.patch +++ /dev/null @@ -1,286 +0,0 @@ -From e2b699df7f05e53b5038b36cddb330976f022d7c Mon Sep 17 00:00:00 2001 -From: Demi Marie Obenour -Date: Wed, 28 Apr 2021 15:37:39 +0530 -Subject: [PATCH] Fix OpenPGP parsing bugs - -- signatures of the wrong type were accepted -- signatures were allowed to contain multiple packets -- numerous out-of-bounds reads -- undefined pointer arithmetic - -Changes to rpmio/rpmpgp.h from original patch are dropped. ---- - rpmio/rpmpgp.c | 132 ++++++++++++++++++++++++++++--------------------- - 1 file changed, 76 insertions(+), 56 deletions(-) - -diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c -index 061751a4d..f01a22705 100644 ---- a/rpmio/rpmpgp.c -+++ b/rpmio/rpmpgp.c -@@ -316,20 +316,49 @@ size_t pgpLen(const uint8_t *s, size_t slen, size_t * lenp) - if (*s < 192) { - lenlen = 1; - dlen = *s; -- } else if (*s < 255 && slen > 2) { -+ } else if (*s < 224 && slen > 2) { - lenlen = 2; - dlen = (((s[0]) - 192) << 8) + s[1] + 192; -- } else if (slen > 5) { -+ } else if (slen > 5 && *s == 255) { - lenlen = 5; - dlen = pgpGrab(s+1, 4); - } - -+ /* Check that the buffer can hold the computed amount of bytes */ -+ if (slen - lenlen < dlen) -+ lenlen = 0; - if (lenlen) - *lenp = dlen; - - return lenlen; - } - -+/** \ingroup rpmpgp -+ * Read a length field `nbytes` long. Checks that the buffer is big enough to -+ * hold `nbytes + *valp` bytes. -+ * @param s pointer to read from -+ * @param nbytes length of length field -+ * @param send pointer past end of buffer -+ * @param[out] *valp decoded length -+ * @return 0 if buffer can hold `nbytes + *valp` of data, -+ * otherwise -1. -+ */ -+static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send, -+ size_t *valp) -+{ -+ int rc = -1; -+ -+ if (nbytes <= send - s) { -+ unsigned int val = pgpGrab(s, nbytes); -+ if (val <= send - s - nbytes) { -+ rc = 0; -+ *valp = val; -+ } -+ } -+ -+ return rc; -+} -+ - struct pgpPkt { - uint8_t tag; /* decoded PGP tag */ - const uint8_t *head; /* pointer to start of packet (header) */ -@@ -342,7 +371,7 @@ static int decodePkt(const uint8_t *p, size_t plen, struct pgpPkt *pkt) - int rc = -1; /* assume failure */ - - /* Valid PGP packet header must always have two or more bytes in it */ -- if (p && plen >= 2 && p[0] & 0x80) { -+ if (p && plen >= 2 && (p[0] & 0x80)) { - size_t lenlen = 0; - size_t hlen = 0; - -@@ -353,15 +382,14 @@ static int decodePkt(const uint8_t *p, size_t plen, struct pgpPkt *pkt) - } else { - /* Old format packet, body length encoding in tag byte */ - lenlen = (1 << (p[0] & 0x3)); -- if (plen > lenlen) { -- pkt->blen = pgpGrab(p+1, lenlen); -- } -+ if (lenlen > 4 || pgpGet(p + 1, lenlen, p + plen, &pkt->blen)) -+ return rc; - pkt->tag = (p[0] >> 2) & 0xf; - } - hlen = lenlen + 1; - - /* Does the packet header and its body fit in our boundaries? */ -- if (lenlen && (hlen + pkt->blen <= plen)) { -+ if (lenlen) { - pkt->head = p; - pkt->body = pkt->head + hlen; - rc = 0; -@@ -414,7 +442,7 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype, - - while (hlen > 0) { - i = pgpLen(p, hlen, &plen); -- if (i == 0 || plen < 1 || i + plen > hlen) -+ if (i == 0 || plen < 1) - break; - - p += i; -@@ -520,9 +548,9 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - int i; - pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo); - -- for (i = 0; i < sigalg->mpis && p + 2 <= pend; i++) { -+ for (i = 0; i < sigalg->mpis && 2 < pend - p; i++) { - int mpil = pgpMpiLen(p); -- if (p + mpil > pend) -+ if (mpil > pend - p) - break; - if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { - if (sigalg->setmpi(sigalg, i, p)) -@@ -544,25 +572,12 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, - return rc; - } - --static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send, -- unsigned int *valp) --{ -- int rc = -1; -- -- if (s + nbytes <= send) { -- *valp = pgpGrab(s, nbytes); -- rc = 0; -- } -- -- return rc; --} -- - static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - pgpDigParams _digp) - { - uint8_t version = 0; -- uint8_t * p; -- unsigned int plen; -+ const uint8_t * p; -+ size_t plen; - int rc = 1; - - if (pgpVersion(h, hlen, &version)) -@@ -604,6 +619,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - } break; - case 4: - { pgpPktSigV4 v = (pgpPktSigV4)h; -+ const uint8_t *const hend = h + hlen; - - if (hlen <= sizeof(*v)) - return 1; -@@ -614,15 +630,12 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype); - pgpPrtNL(); - -- p = &v->hashlen[0]; -- if (pgpGet(v->hashlen, sizeof(v->hashlen), h + hlen, &plen)) -- return 1; -- p += sizeof(v->hashlen); -- -- if ((p + plen) > (h + hlen)) -+ if (pgpGet(v->hashlen, sizeof(v->hashlen), hend, &plen)) - return 1; -+ p = h + sizeof *v; - - if (_digp->pubkey_algo == 0) { -+ /* Get the hashed data */ - _digp->hashlen = sizeof(*v) + plen; - _digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen); - } -@@ -630,18 +643,15 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - return 1; - p += plen; - -- if (pgpGet(p, 2, h + hlen, &plen)) -+ if (pgpGet(p, 2, hend, &plen)) - return 1; - p += 2; - -- if ((p + plen) > (h + hlen)) -- return 1; -- - if (pgpPrtSubType(p, plen, v->sigtype, _digp)) - return 1; - p += plen; - -- if (pgpGet(p, 2, h + hlen, &plen)) -+ if (hend - p < 2) - return 1; - pgpPrtHex(" signhash16", p, 2); - pgpPrtNL(); -@@ -654,11 +664,8 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, - memcpy(_digp->signhash16, p, sizeof(_digp->signhash16)); - } - -- p += 2; -- if (p > (h + hlen)) -- return 1; -- -- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); -+ rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p + 2, h, hlen, -+ _digp); - } break; - default: - rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); -@@ -692,9 +699,9 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo, - int i; - pgpDigAlg keyalg = pgpPubkeyNew(pubkey_algo); - -- for (i = 0; i < keyalg->mpis && p + 2 <= pend; i++) { -+ for (i = 0; i < keyalg->mpis && 2 < pend - p; i++) { - int mpil = pgpMpiLen(p); -- if (p + mpil > pend) -+ if (mpil > pend - p) - break; - if (keyalg->setmpi(keyalg, i, p)) - break; -@@ -785,20 +792,27 @@ int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen, - int mpis = -1; - - /* Packet must be larger than v to have room for the required MPIs */ -- if (hlen > sizeof(*v)) { -- switch (v->pubkey_algo) { -- case PGPPUBKEYALGO_RSA: -- mpis = 2; -- break; -- case PGPPUBKEYALGO_DSA: -- mpis = 4; -- break; -- } -- } -+ if (hlen <= sizeof(*v)) -+ return rc; -+ se = (uint8_t *)(v + 1); -+ -+ switch (v->pubkey_algo) { -+ case PGPPUBKEYALGO_RSA: -+ mpis = 2; -+ break; -+ case PGPPUBKEYALGO_DSA: -+ mpis = 4; -+ break; -+ default: -+ return rc; -+ } - -- se = (uint8_t *)(v + 1); -- while (se < pend && mpis-- > 0) -- se += pgpMpiLen(se); -+ while (pend - se >= 2 && mpis-- > 0) { -+ int i = pgpMpiLen(se); -+ if (pend - se < i) -+ return rc; -+ se += i; -+ } - - /* Does the size and number of MPI's match our expectations? */ - if (se == pend && mpis == 0) { -@@ -1025,6 +1039,8 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, - break; - - p += (pkt.body - pkt.head) + pkt.blen; -+ if (pkttype == PGPTAG_SIGNATURE) -+ break; - } - - rc = (digp && (p == pend)) ? 0 : -1; -@@ -1147,6 +1163,10 @@ rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx) - if (sig == NULL || ctx == NULL) - goto exit; - -+ /* RPM signatures are always binary */ -+ if (sig->sigtype != PGPSIGTYPE_BINARY) -+ goto exit; -+ - if (sig->hash != NULL) - rpmDigestUpdate(ctx, sig->hash, sig->hashlen); - --- -2.17.1 - diff --git a/SPECS/rpm/rpm.spec b/SPECS/rpm/rpm.spec index 25a9a011cd..5b866ea909 100644 --- a/SPECS/rpm/rpm.spec +++ b/SPECS/rpm/rpm.spec @@ -7,7 +7,7 @@ Summary: Package manager Name: rpm Version: 4.14.3 -Release: 4%{?dist} +Release: 5%{?dist} License: GPLv2+ URL: http://rpm.org Group: Applications/System @@ -25,13 +25,10 @@ Source5: macros.python3 Patch0: find-debuginfo-do-not-generate-dir-entries.patch Patch1: CVE-2021-20271.patch -Patch2: Fix-OpenPGP-parsing-bugs.patch -Patch3: Header-signatures-alone-are-not-sufficient.patch -Patch4: CVE-2021-20266.patch -Patch5: Fix-regression-reading-rpm-v3.patch -Patch6: CVE-2021-3521-1.patch -Patch7: CVE-2021-3521-2.patch -Patch8: CVE-2021-3521-3.patch +Patch2: Header-signatures-alone-are-not-sufficient.patch +Patch3: CVE-2021-20266.patch +Patch4: Fix-regression-reading-rpm-v3.patch +Patch5: CVE-2021-3521.patch Requires: bash Requires: libdb @@ -286,6 +283,9 @@ rm -rf %{buildroot} %{python3_sitelib}/* %changelog +* Wed Sep 14 2022 Shreenidhi Shedi 4.14.3-5 +- Further fixes to CVE-2021-3521 +- Remove pgp related fixes, it's not used by other distros * Tue Aug 30 2022 Shreenidhi Shedi 4.14.3-4 - Fix CVE-2021-3521 * Fri Jul 08 2022 Harinadh D 4.14.3-3