From 8a4b8c5cfec865585a72c8e22311e6e43bc6539f Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Thu, 20 Apr 2023 14:55:16 +0300 Subject: [PATCH] Backport improved crypto error messages from upstream --- ...gpVerifySignature2-and-pgpPrtParams2.patch | 267 ++++++++++++++++++ rpm.spec | 9 +- 2 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 0001-Add-pgpVerifySignature2-and-pgpPrtParams2.patch diff --git a/0001-Add-pgpVerifySignature2-and-pgpPrtParams2.patch b/0001-Add-pgpVerifySignature2-and-pgpPrtParams2.patch new file mode 100644 index 0000000..b00d377 --- /dev/null +++ b/0001-Add-pgpVerifySignature2-and-pgpPrtParams2.patch @@ -0,0 +1,267 @@ +From e75ae70ef1a152dac9a066506cafd2bbf7b2565e Mon Sep 17 00:00:00 2001 +Message-Id: +From: "Neal H. Walfield" +Date: Wed, 12 Apr 2023 17:56:19 +0200 +Subject: [PATCH] Add pgpVerifySignature2() and pgpPrtParams2() + +Add new functions pgpVerifySignature2() and pgpPrtParams2(), which are +like their earlier versions, but optionally return descriptive error +messages (in the case of failure) or lints (in the case of success). +Adjust tests accordingly. + +This requires rpm-sequoia 1.4 or later. + +See https://github.com/rpm-software-management/rpm-sequoia/issues/39 +and +https://github.com/rpm-software-management/rpm/issues/2127#issuecomment-1482646398 + +Fixes #2483. + +This is a backport of commit 87b9e0c28c3df3937f6676ee1b4164d6154dd9d3 +--- + configure.ac | 2 +- + include/rpm/rpmpgp.h | 23 +++++++++++++++++++++++ + lib/rpmvs.c | 19 ++++++++++++++++--- + rpmio/rpmkeyring.c | 7 ++++++- + rpmio/rpmpgp_internal.c | 15 +++++++++++++++ + rpmio/rpmpgp_sequoia.c | 7 +++++++ + tests/rpmi.at | 10 ++++++++-- + tests/rpmsigdig.at | 20 +++++++++++++++++--- + 9 files changed, 95 insertions(+), 10 deletions(-) + +diff --git a/configure.ac b/configure.ac +index e6676c581..1d173e4e2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -384,7 +384,7 @@ AC_SUBST(WITH_LIBGCRYPT_LIB) + WITH_RPM_SEQUOIA_INCLUDE= + WITH_RPM_SEQUOIA_LIB= + if test "$with_crypto" = sequoia ; then +- PKG_CHECK_MODULES([RPM_SEQUOIA], [rpm-sequoia], [have_rpm_sequoia=yes], [have_rpm_sequoia=no]) ++ PKG_CHECK_MODULES([RPM_SEQUOIA], [rpm-sequoia >= 1.4.0], [have_rpm_sequoia=yes], [have_rpm_sequoia=no]) + if test "$have_rpm_sequoia" = "yes"; then + WITH_RPM_SEQUOIA_INCLUDE="$RPM_SEQUOIA_CFLAGS" + WITH_RPM_SEQUOIA_LIB="$RPM_SEQUOIA_LIBS" +diff --git a/include/rpm/rpmpgp.h b/include/rpm/rpmpgp.h +index a3238a643..3352129b8 100644 +--- a/include/rpm/rpmpgp.h ++++ b/include/rpm/rpmpgp.h +@@ -1013,6 +1013,18 @@ int pgpPubkeyKeyID(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid); + int pgpPrtParams(const uint8_t *pkts, size_t pktlen, unsigned int pkttype, + pgpDigParams * ret); + ++/** \ingroup rpmpgp ++ * Parse a OpenPGP packet(s). ++ * @param pkts OpenPGP packet(s) ++ * @param pktlen OpenPGP packet(s) length (no. of bytes) ++ * @param pkttype Expected packet type (signature/key) or 0 for any ++ * @param[out] ret signature/pubkey packet parameters on success (alloced) ++ * @param[out] lints error messages and lints ++ * @return -1 on error, 0 on success ++ */ ++int pgpPrtParams2(const uint8_t *pkts, size_t pktlen, unsigned int pkttype, ++ pgpDigParams * ret, char **lints); ++ + /** \ingroup rpmpgp + * Parse subkey parameters from OpenPGP packet(s). + * @param pkts OpenPGP packet(s) +@@ -1191,6 +1203,17 @@ const uint8_t *pgpDigParamsSignID(pgpDigParams digp); + */ + const char *pgpDigParamsUserID(pgpDigParams digp); + ++/** \ingroup rpmpgp ++ * Verify a PGP signature and return a error message or lint. ++ * @param key public key ++ * @param sig signature ++ * @param hashctx digest context ++ * @param lints error messages and lints ++ * @return RPMRC_OK on success ++ */ ++rpmRC pgpVerifySignature2(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx, ++ char **lints); ++ + /** \ingroup rpmpgp + * Retrieve the object's version. + * +diff --git a/lib/rpmvs.c b/lib/rpmvs.c +index a1425ea17..9b2106927 100644 +--- a/lib/rpmvs.c ++++ b/lib/rpmvs.c +@@ -193,10 +193,23 @@ static void rpmsinfoInit(const struct vfyinfo_s *vinfo, + } + + if (sinfo->type == RPMSIG_SIGNATURE_TYPE) { +- if (pgpPrtParams(data, dlen, PGPTAG_SIGNATURE, &sinfo->sig)) { +- rasprintf(&sinfo->msg, _("%s tag %u: invalid OpenPGP signature"), +- origin, td->tag); ++ char *lints = NULL; ++ int ec = pgpPrtParams2(data, dlen, PGPTAG_SIGNATURE, &sinfo->sig, &lints); ++ if (ec) { ++ if (lints) { ++ rasprintf(&sinfo->msg, ++ ("%s tag %u: invalid OpenPGP signature: %s"), ++ origin, td->tag, lints); ++ free(lints); ++ } else { ++ rasprintf(&sinfo->msg, ++ _("%s tag %u: invalid OpenPGP signature"), ++ origin, td->tag); ++ } + goto exit; ++ } else if (lints) { ++ rpmlog(RPMLOG_WARNING, "%s\n", lints); ++ free(lints); + } + sinfo->hashalgo = pgpDigParamsAlgo(sinfo->sig, PGPVAL_HASHALGO); + sinfo->keyid = pgpGrab(pgpDigParamsSignID(sinfo->sig)+4, 4); +diff --git a/rpmio/rpmkeyring.c b/rpmio/rpmkeyring.c +index db72892d9..712004bc8 100644 +--- a/rpmio/rpmkeyring.c ++++ b/rpmio/rpmkeyring.c +@@ -328,7 +328,12 @@ rpmRC rpmKeyringVerifySig(rpmKeyring keyring, pgpDigParams sig, DIGEST_CTX ctx) + pgpkey = key->pgpkey; + + /* We call verify even if key not found for a signature sanity check */ +- rc = pgpVerifySignature(pgpkey, sig, ctx); ++ char *lints = NULL; ++ rc = pgpVerifySignature2(pgpkey, sig, ctx, &lints); ++ if (lints) { ++ rpmlog(rc ? RPMLOG_ERR : RPMLOG_WARNING, "%s\n", lints); ++ free(lints); ++ } + } + + if (keyring) +diff --git a/rpmio/rpmpgp_internal.c b/rpmio/rpmpgp_internal.c +index 0fcd220e4..a049c09b2 100644 +--- a/rpmio/rpmpgp_internal.c ++++ b/rpmio/rpmpgp_internal.c +@@ -1095,6 +1095,14 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, + return rc; + } + ++int pgpPrtParams2(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, ++ pgpDigParams * ret, char **lints) ++{ ++ if (lints) ++ *lints = NULL; ++ return pgpPrtParams(pkts, pktlen, pkttype, ret); ++} ++ + int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + pgpDigParams mainkey, pgpDigParams **subkeys, + int *subkeysCount) +@@ -1264,6 +1272,13 @@ rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx) + pgpDigGetParams(dig, PGPTAG_SIGNATURE), hashctx); + } + ++rpmRC pgpVerifySignature2(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx, char **lints) ++{ ++ if (lints) ++ *lints = NULL; ++ return pgpVerifySignature(key, sig, hashctx); ++} ++ + static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen) + { + const char * enc = NULL; +diff --git a/rpmio/rpmpgp_sequoia.c b/rpmio/rpmpgp_sequoia.c +index e01acd0e9..2141bbf30 100644 +--- a/rpmio/rpmpgp_sequoia.c ++++ b/rpmio/rpmpgp_sequoia.c +@@ -36,6 +36,9 @@ W(uint32_t, pgpDigParamsCreationTime, (pgpDigParams digp), (digp)) + W(rpmRC, pgpVerifySignature, + (pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx), + (key, sig, hashctx)) ++W(rpmRC, pgpVerifySignature2, ++ (pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx, char **lints), ++ (key, sig, hashctx, lints)) + W(int, pgpPubkeyKeyID, + (const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid), + (pkt, pktlen, keyid)) +@@ -51,6 +54,10 @@ W(int, pgpPubKeyCertLen, + W(int, pgpPrtParams, + (const uint8_t *pkts, size_t pktlen, unsigned int pkttype, pgpDigParams *ret), + (pkts, pktlen, pkttype, ret)) ++W(int, pgpPrtParams2, ++ (const uint8_t *pkts, size_t pktlen, unsigned int pkttype, pgpDigParams *ret, ++ char **lints), ++ (pkts, pktlen, pkttype, ret, lints)) + W(int, pgpPrtParamsSubkeys, + (const uint8_t *pkts, size_t pktlen, + pgpDigParams mainkey, pgpDigParams **subkeys, +diff --git a/tests/rpmi.at b/tests/rpmi.at +index 7c8f25eff..d67185d5b 100644 +--- a/tests/rpmi.at ++++ b/tests/rpmi.at +@@ -254,7 +254,7 @@ AT_CLEANUP + + AT_SETUP([rpm -U ]) + AT_KEYWORDS([install]) +-AT_CHECK([ ++AT_CHECK_UNQUOTED([ + RPMDB_INIT + + pkg="hello-2.0-1.x86_64-signed.rpm" +@@ -267,7 +267,13 @@ runroot rpm -U --ignorearch --ignoreos --nodeps \ + ], + [1], + [], +-[error: /tmp/hello-2.0-1.x86_64-signed.rpm: Header RSA signature: BAD (package tag 268: invalid OpenPGP signature) ++[`if test x$PGP = xinternal; then ++ echo 'error: /tmp/hello-2.0-1.x86_64-signed.rpm: Header RSA signature: BAD (package tag 268: invalid OpenPGP signature)' ++else ++ echo 'error: /tmp/hello-2.0-1.x86_64-signed.rpm: Header RSA signature: BAD (package tag 268: invalid OpenPGP signature: Parsing an OpenPGP packet:' ++ echo ' Failed to parse Signature Packet' ++ echo ' because: Malformed packet: Subpacket extends beyond the end of the subpacket area)' ++fi` + error: /tmp/hello-2.0-1.x86_64-signed.rpm cannot be installed + ]) + AT_CLEANUP +diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at +index 5b1c6c4a6..e5482735a 100644 +--- a/tests/rpmsigdig.at ++++ b/tests/rpmsigdig.at +@@ -539,7 +539,7 @@ AT_CLEANUP + # Test pre-built corrupted package verification (corrupted signature) + AT_SETUP([rpmkeys -Kv 1]) + AT_KEYWORDS([rpmkeys digest signature]) +-AT_CHECK([ ++AT_CHECK_UNQUOTED([ + RPMDB_INIT + + pkg="hello-2.0-1.x86_64-signed.rpm" +@@ -553,14 +553,28 @@ runroot rpmkeys -Kv /tmp/${pkg} + ], + [1], + [/tmp/hello-2.0-1.x86_64-signed.rpm: +- Header RSA signature: BAD (package tag 268: invalid OpenPGP signature) ++`if test x$PGP = xinternal; then ++ echo ' Header RSA signature: BAD (package tag 268: invalid OpenPGP signature)' ++else ++ echo ' Header RSA signature: BAD (package tag 268: invalid OpenPGP signature: Parsing an OpenPGP packet:' ++ echo ' Failed to parse Signature Packet' ++ echo ' because: Signature appears to be created by a non-conformant OpenPGP implementation, see .' ++ echo ' because: Malformed MPI: leading bit is not set: expected bit 1 to be set in 0 (0))' ++fi` + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 digest: OK + V4 RSA/SHA256 Signature, key ID 1964c5fc: NOKEY + MD5 digest: OK + /tmp/hello-2.0-1.x86_64-signed.rpm: +- Header RSA signature: BAD (package tag 268: invalid OpenPGP signature) ++`if test x$PGP = xinternal; then ++ echo ' Header RSA signature: BAD (package tag 268: invalid OpenPGP signature)' ++else ++ echo ' Header RSA signature: BAD (package tag 268: invalid OpenPGP signature: Parsing an OpenPGP packet:' ++ echo ' Failed to parse Signature Packet' ++ echo ' because: Signature appears to be created by a non-conformant OpenPGP implementation, see .' ++ echo ' because: Malformed MPI: leading bit is not set: expected bit 1 to be set in 0 (0))' ++fi` + Header SHA256 digest: OK + Header SHA1 digest: OK + Payload SHA256 digest: OK +-- +2.40.0 + diff --git a/rpm.spec b/rpm.spec index 3638b6b..cc6e70b 100644 --- a/rpm.spec +++ b/rpm.spec @@ -32,7 +32,7 @@ %global rpmver 4.18.1 #global snapver rc1 -%global baserelease 1 +%global baserelease 2 %global sover 9 %global srcver %{rpmver}%{?snapver:-%{snapver}} @@ -97,7 +97,7 @@ BuildRequires: sqlite-devel %if %{with sequoia} %global crypto sequoia -BuildRequires: rpm-sequoia-devel >= 1.0.0 +BuildRequires: rpm-sequoia-devel >= 1.4.0 %else %global crypto openssl BuildRequires: openssl-devel @@ -134,7 +134,7 @@ rpm-4.18.x-siteconfig.patch rpm-4.9.90-no-man-dirs.patch # Patches already upstream: -# ... +0001-Add-pgpVerifySignature2-and-pgpPrtParams2.patch # These are not yet upstream rpm-4.7.1-geode-i686.patch @@ -618,6 +618,9 @@ fi %doc docs/librpm/html/* %changelog +* Thu Apr 20 2023 Panu Matilainen - 4.18.1-2 +- Backport improved crypto error messages from upstream + * Wed Mar 15 2023 Michal Domonkos - 4.18.1-1 - Rebase to rpm 4.18.1 (https://rpm.org/wiki/Releases/4.18.1)