diff --git a/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch b/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch
new file mode 100644
index 0000000..70c2a0b
--- /dev/null
+++ b/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch
@@ -0,0 +1,36 @@
+From 7f0b7217fb1c20ec6ce0c0e0bfee0349f27a2511 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Fri, 8 Jan 2021 13:59:59 +0200
+Subject: [PATCH] Ensure ELF files get stripped when debuginfo is disabled
+
+Depending on libmagic version, PIE executables can be reported as
+"shared object" avoiding the strip. And so will any libraries because
+we're explicitly skipping them for whatever historical reason - perhaps
+because there's a separate script for stripping the libraries, but that
+has been never enabled in rpm, and relying on "file" strings to do this
+is hopelessly unreliable.
+
+Also drop file permissions checks: making shared libraries executable
+just to have them stripped is not sensical, especially in the light of
+commit 80818e4f902ba3cf85e4cfcd8a7a4c71c601f3cf
+
+Reported once upon time as RhBug:988812 and later RhBug:1634084
+---
+ scripts/brp-strip | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/scripts/brp-strip b/scripts/brp-strip
+index c3484fe3c..35fbb593a 100755
+--- a/scripts/brp-strip
++++ b/scripts/brp-strip
+@@ -13,5 +13,5 @@ Darwin*) exit 0 ;;
+ esac
+ 
+ # Strip ELF binaries
+-find "$RPM_BUILD_ROOT" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \
+-    xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | grep -v ' shared object,' | sed -n -e 's/^\(.*\):[ 	]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
++find "$RPM_BUILD_ROOT" -type f \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \
++    xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed -n -e 's/^\(.*\):[ 	]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0
+-- 
+2.33.1
+
diff --git a/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch b/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch
new file mode 100644
index 0000000..9be13e7
--- /dev/null
+++ b/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch
@@ -0,0 +1,194 @@
+From 495f25f7198fb1e0163a7ae55de55576d9dc6fe5 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Mon, 29 Nov 2021 14:01:39 +0200
+Subject: [PATCH] Fix IMA signature lengths assumed constant (#1833,
+ RhBug:2018937)
+
+At least ECDSA and RSA signatures can vary in length, but the IMA code
+assumes constant lengths and thus may either place invalid signatures on
+disk from either truncating or overshooting, and segfault if the stars are
+just so.
+
+Luckily the signatures are stored as strings so we can calculate the
+actual lengths at runtime and ignore the stored constant length info.
+Extend hex2bin() to optionally calculate the lengths and maximum,
+and use these for returning IMA data from the rpmfi(les) API.
+
+Additionally update the signing code to store the largest IMA signature
+length rather than what happened to be last to be on the safe side.
+We can't rely on this value due to invalid packages being out there,
+but then we need to calculate the lengths on rpmfiles populate so there's
+not a lot to gain anyhow.
+
+Fixes: #1833
+
+Combined with 0c1ad364d65c4144ff71c376e0b49fbc322b686d and backported
+for 4.16.1.3.  Note that the test case has been removed due to it
+including a binary file (test package) for which we'd have to use -Sgit
+with %autopatch and thus depend on git-core at build time.
+Nevertheless, we do have this BZ covered in our internal test suite, so
+no need for it anyway.
+---
+ lib/rpmfi.c          | 43 ++++++++++++++++++++++++++++++++++---------
+ python/rpmfiles-py.c | 18 ++++++++++++++++++
+ sign/rpmsignfiles.c  |  5 ++++-
+ 3 files changed, 56 insertions(+), 10 deletions(-)
+
+diff --git a/lib/rpmfi.c b/lib/rpmfi.c
+index af428468c..0878d78f2 100644
+--- a/lib/rpmfi.c
++++ b/lib/rpmfi.c
+@@ -115,7 +115,8 @@ struct rpmfiles_s {
+     struct fingerPrint_s * fps;	/*!< File fingerprint(s). */
+ 
+     int digestalgo;		/*!< File digest algorithm */
+-    int signaturelength;	/*!< File signature length */
++    int *signaturelengths;	/*!< File signature length */
++    int signaturemaxlen;	/*!< Largest file signature length */
+     unsigned char * digests;	/*!< File digests in binary. */
+     unsigned char * signatures; /*!< File signatures in binary. */
+ 
+@@ -575,9 +576,9 @@ const unsigned char * rpmfilesFSignature(rpmfiles fi, int ix, size_t *len)
+ 
+     if (fi != NULL && ix >= 0 && ix < rpmfilesFC(fi)) {
+ 	if (fi->signatures != NULL)
+-	    signature = fi->signatures + (fi->signaturelength * ix);
++	    signature = fi->signatures + (fi->signaturemaxlen * ix);
+ 	if (len)
+-	    *len = fi->signaturelength;
++	    *len = fi->signaturelengths[ix];
+     }
+     return signature;
+ }
+@@ -1257,6 +1258,7 @@ rpmfiles rpmfilesFree(rpmfiles fi)
+ 	fi->flangs = _free(fi->flangs);
+ 	fi->digests = _free(fi->digests);
+ 	fi->signatures = _free(fi->signatures);
++	fi->signaturelengths = _free(fi->signaturelengths);
+ 	fi->fcaps = _free(fi->fcaps);
+ 
+ 	fi->cdict = _free(fi->cdict);
+@@ -1486,15 +1488,38 @@ err:
+ }
+ 
+ /* Convert a tag of hex strings to binary presentation */
+-static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len)
++/* If lengths is non-NULL, assume variable length strings */
++static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len,
++			int **lengths, int *maxlen)
+ {
+     struct rpmtd_s td;
+     uint8_t *bin = NULL;
+ 
+     if (headerGet(h, tag, &td, HEADERGET_MINMEM) && rpmtdCount(&td) == num) {
+-	uint8_t *t = bin = xmalloc(num * len);
+ 	const char *s;
+ 
++	/* Figure string sizes + max length for allocation purposes */
++	if (lengths) {
++	    int maxl = 0;
++	    int *lens = xmalloc(num * sizeof(*lens));
++	    int i = 0;
++
++	    while ((s = rpmtdNextString(&td))) {
++		lens[i] = strlen(s) / 2;
++		if (lens[i] > maxl)
++		    maxl = lens[i];
++		i++;
++	    }
++
++	    *lengths = lens;
++	    *maxlen = maxl;
++	    len = maxl;
++
++	    /* Reinitialize iterator for next round */
++	    rpmtdInit(&td);
++	}
++
++	uint8_t *t = bin = xmalloc(num * len);
+ 	while ((s = rpmtdNextString(&td))) {
+ 	    if (*s == '\0') {
+ 		memset(t, 0, len);
+@@ -1570,15 +1595,15 @@ static int rpmfilesPopulate(rpmfiles fi, Header h, rpmfiFlags flags)
+     /* grab hex digests from header and store in binary format */
+     if (!(flags & RPMFI_NOFILEDIGESTS)) {
+ 	size_t diglen = rpmDigestLength(fi->digestalgo);
+-	fi->digests = hex2bin(h, RPMTAG_FILEDIGESTS, totalfc, diglen);
++	fi->digests = hex2bin(h, RPMTAG_FILEDIGESTS, totalfc, diglen,
++				NULL, NULL);
+     }
+ 
+     fi->signatures = NULL;
+     /* grab hex signatures from header and store in binary format */
+     if (!(flags & RPMFI_NOFILESIGNATURES)) {
+-	fi->signaturelength = headerGetNumber(h, RPMTAG_FILESIGNATURELENGTH);
+-	fi->signatures = hex2bin(h, RPMTAG_FILESIGNATURES,
+-				 totalfc, fi->signaturelength);
++	fi->signatures = hex2bin(h, RPMTAG_FILESIGNATURES, totalfc, 0,
++				&fi->signaturelengths, &fi->signaturemaxlen);
+     }
+ 
+     /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */
+diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c
+index 27666021d..48189a0ac 100644
+--- a/python/rpmfiles-py.c
++++ b/python/rpmfiles-py.c
+@@ -152,6 +152,22 @@ static PyObject *rpmfile_digest(rpmfileObject *s)
+     Py_RETURN_NONE;
+ }
+ 
++static PyObject *bytebuf(const unsigned char *buf, size_t len)
++{
++    if (buf) {
++	PyObject *o = PyBytes_FromStringAndSize((const char *)buf, len);
++	return o;
++    }
++    Py_RETURN_NONE;
++}
++
++static PyObject *rpmfile_imasig(rpmfileObject *s)
++{
++    size_t len = 0;
++    const unsigned char *sig = rpmfilesFSignature(s->files, s->ix, &len);
++    return bytebuf(sig, len);
++}
++
+ static PyObject *rpmfile_class(rpmfileObject *s)
+ {
+     return utf8FromString(rpmfilesFClass(s->files, s->ix));
+@@ -278,6 +294,8 @@ static PyGetSetDef rpmfile_getseters[] = {
+       "language the file provides (typically for doc files)" },
+     { "caps",		(getter) rpmfile_caps,		NULL,
+       "file capabilities" },
++    { "imasig",	(getter) rpmfile_imasig,	NULL,
++      "IMA signature" },
+     { NULL, NULL, NULL, NULL }
+ };
+ 
+diff --git a/sign/rpmsignfiles.c b/sign/rpmsignfiles.c
+index b143c5b9b..6f39db6be 100644
+--- a/sign/rpmsignfiles.c
++++ b/sign/rpmsignfiles.c
+@@ -98,8 +98,9 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass)
+     td.count = 1;
+ 
+     while (rpmfiNext(fi) >= 0) {
++	uint32_t slen;
+ 	digest = rpmfiFDigest(fi, NULL, NULL);
+-	signature = signFile(algoname, digest, diglen, key, keypass, &siglen);
++	signature = signFile(algoname, digest, diglen, key, keypass, &slen);
+ 	if (!signature) {
+ 	    rpmlog(RPMLOG_ERR, _("signFile failed\n"));
+ 	    goto exit;
+@@ -110,6 +111,8 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass)
+ 	    goto exit;
+ 	}
+ 	signature = _free(signature);
++	if (slen > siglen)
++	    siglen = slen;
+     }
+ 
+     if (siglen > 0) {
+-- 
+2.33.1
+
diff --git a/rpm-4.16.1.3-support-bdb-hash-v8.patch b/rpm-4.16.1.3-support-bdb-hash-v8.patch
new file mode 100644
index 0000000..3581544
--- /dev/null
+++ b/rpm-4.16.1.3-support-bdb-hash-v8.patch
@@ -0,0 +1,39 @@
+From c771ae28e28b2971869b7801ffc7961f4dcb6544 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 10 Jun 2021 10:32:12 +0300
+Subject: [PATCH] Support hash v8 databases from BDB < 4.6 in bdb_ro
+
+In Hash v8 databases page type differs from newer ones to denote
+the difference between sorted and unsorted pages.
+
+Fixes reading rpm databases from older distros like SLES 11 and RHEL 5
+(RhBug:1965147)
+---
+ lib/backend/bdb_ro.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/lib/backend/bdb_ro.c b/lib/backend/bdb_ro.c
+index 2667ec845..695ef78e3 100644
+--- a/lib/backend/bdb_ro.c
++++ b/lib/backend/bdb_ro.c
+@@ -276,7 +276,7 @@ static int hash_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned i
+     pg = hash_bucket_to_page(cur->db, bucket);
+     if (bdb_getpage(cur->db, cur->page, pg))
+ 	return -1;
+-    if (cur->page[25] != 8 && cur->page[25] != 13)
++    if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2)
+ 	return -1;
+     cur->idx = (unsigned int)-2;
+     cur->numidx = *(uint16_t *)(cur->page + 20);
+@@ -323,7 +323,7 @@ static int hash_next(struct bdb_cur *cur)
+ 	    }
+ 	    if (bdb_getpage(cur->db, cur->page, pg))
+ 		return -1;
+-	    if (cur->page[25] != 8 && cur->page[25] != 13)
++	    if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2)
+ 		return -1;
+ 	    cur->numidx = *(uint16_t *)(cur->page + 20);
+ 	    continue;
+-- 
+2.33.1
+
diff --git a/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch b/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch
new file mode 100644
index 0000000..43184bc
--- /dev/null
+++ b/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch
@@ -0,0 +1,144 @@
+From 137ecc2e1841c2b27b99d4db9006253dd1c73dde Mon Sep 17 00:00:00 2001
+From: Michael Schroeder <mls@suse.de>
+Date: Fri, 4 Jun 2021 23:30:49 +0200
+Subject: [PATCH] Unbreak checking of installed rich dependencies
+
+Commit ddb32b9187e9ce85819a84ca8d202131fd9f8b9f added an
+extra check that tests if the provide we are checking really
+intersects the dependency from rpmdb. Unfortunately the
+rpmdsCompare() call does not understand rich dependencies and
+will consider them as not intersecting.
+
+Unbreak the check by not doing the intersection test for
+rich dependencies. We'll improve this in a later commit.
+
+Also add test cases for dependency problems with installed
+rich dependencies.
+---
+ lib/depends.c    |  2 +-
+ tests/rpmdeps.at | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 100 insertions(+), 1 deletion(-)
+
+diff --git a/lib/depends.c b/lib/depends.c
+index c10ba4bda..fecbd9675 100644
+--- a/lib/depends.c
++++ b/lib/depends.c
+@@ -846,7 +846,7 @@ static void checkInstDeps(rpmts ts, depCache dcache, rpmte te,
+ 	rpmdsSetIx(ds, rpmdbGetIteratorFileNum(mi));
+ 
+ 	/* Is it in our range at all? (but file deps have no range) */
+-	if (depds)
++	if (depds && !rpmdsIsRich(ds))
+ 	    match = rpmdsCompare(ds, depds);
+ 
+ 	if (match && unsatisfiedDepend(ts, dcache, ds) == is_problem) {
+diff --git a/tests/rpmdeps.at b/tests/rpmdeps.at
+index 67bde1dc8..8357af9df 100644
+--- a/tests/rpmdeps.at
++++ b/tests/rpmdeps.at
+@@ -732,3 +732,102 @@ runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarc
+ [],
+ [])
+ AT_CLEANUP
++
++# ------------------------------
++#
++AT_SETUP([install to break installed rich dependency])
++AT_KEYWORDS([install, boolean])
++RPMDB_INIT
++
++runroot rpmbuild --quiet -bb \
++	--define "pkg one" \
++	--define "cfls (deptest-three or deptest-five)" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg two" \
++	--define "reqs (deptest-five if deptest-four)" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg three" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg four" \
++	  /data/SPECS/deptest.spec
++
++# installed conflict with "or" clause
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm
++runroot rpm -U /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm
++],
++[1],
++[],
++[error: Failed dependencies:
++	(deptest-three or deptest-five) conflicts with (installed) deptest-one-1.0-1.noarch
++])
++
++# installed requires with "if" clause
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm
++runroot rpm -U /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm
++],
++[1],
++[],
++[error: Failed dependencies:
++	(deptest-five if deptest-four) is needed by (installed) deptest-two-1.0-1.noarch
++])
++AT_CLEANUP
++
++# ------------------------------
++#
++AT_SETUP([erase to break installed rich dependency])
++AT_KEYWORDS([install, boolean])
++RPMDB_INIT
++
++runroot rpmbuild --quiet -bb \
++	--define "pkg one" \
++	--define "reqs (deptest-three or deptest-five)" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg two" \
++	--define "cfls (deptest-five unless deptest-four)" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg three" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg four" \
++	  /data/SPECS/deptest.spec
++runroot rpmbuild --quiet -bb \
++	--define "pkg five" \
++	  /data/SPECS/deptest.spec
++
++# installed requires with "or" clause
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm
++runroot rpm -e deptest-three
++],
++[1],
++[],
++[error: Failed dependencies:
++	(deptest-three or deptest-five) is needed by (installed) deptest-one-1.0-1.noarch
++])
++
++# installed conflicts with "unless" clause
++AT_CHECK([
++RPMDB_INIT
++
++runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-five-1.0-1.noarch.rpm
++runroot rpm -e deptest-four
++],
++[1],
++[],
++[error: Failed dependencies:
++	(deptest-five unless deptest-four) conflicts with (installed) deptest-two-1.0-1.noarch
++])
++AT_CLEANUP
+-- 
+2.33.1
+
diff --git a/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch b/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch
new file mode 100644
index 0000000..a1753a4
--- /dev/null
+++ b/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch
@@ -0,0 +1,386 @@
+From a73895e6f03bef5e95a738ff680f7c42151f3959 Mon Sep 17 00:00:00 2001
+From: Demi Marie Obenour <demi@invisiblethingslab.com>
+Date: Thu, 6 May 2021 18:34:45 -0400
+Subject: [PATCH] Validate and require subkey binding signatures on PGP public
+ keys
+
+All subkeys must be followed by a binding signature by the primary key
+as per the OpenPGP RFC, enforce the presence and validity in the parser.
+
+The implementation is as kludgey as they come to work around our
+simple-minded parser structure without touching API, to maximise
+backportability. Store all the raw packets internally as we decode them
+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.
+
+Combined with:
+5ff86764b17f31535cb247543a90dd739076ec38
+b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8
+9f03f42e2614a68f589f9db8fe76287146522c0c
+
+Fixes CVE-2021-3521.
+---
+ rpmio/rpmpgp.c                                | 123 +++++++++++++++---
+ 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, 224 insertions(+), 17 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 d0688ebe9..b12410d67 100644
+--- a/rpmio/rpmpgp.c
++++ b/rpmio/rpmpgp.c
+@@ -515,7 +515,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)
+ {
+@@ -528,10 +528,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;
+     }
+ 
+@@ -604,7 +602,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;
+@@ -662,7 +660,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);
+@@ -1041,36 +1039,128 @@ 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;
++    if (pkt->tag == exptag) {
++	uint8_t head[] = {
++	    0x99,
++	    (pkt->blen >> 8),
++	    (pkt->blen     ),
++	};
++
++	rpmDigestUpdate(hash, head, 3);
++	rpmDigestUpdate(hash, pkt->body, pkt->blen);
++	rc = 0;
++    }
++    return rc;
++}
++
++static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
++			const struct pgpPkt *all, int i)
++{
++    int rc = -1;
++    DIGEST_CTX hash = NULL;
++
++    switch (selfsig->sigtype) {
++    case PGPSIGTYPE_SUBKEY_BINDING:
++	hash = rpmDigestInit(selfsig->hash_algo, 0);
++	if (hash) {
++	    rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY);
++	    if (!rc)
++		rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY);
++	}
++	break;
++    default:
++	/* ignore types we can't handle */
++	rc = 0;
++	break;
++    }
++
++    if (hash && rc == 0)
++	rc = pgpVerifySignature(key, selfsig, hash);
++
++    rpmDigestFinal(hash, NULL, NULL, 0);
++
++    return rc;
++}
++
+ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
+ 		 pgpDigParams * ret)
+ {
+     const uint8_t *p = pkts;
+     const uint8_t *pend = pkts + pktlen;
+     pgpDigParams digp = NULL;
+-    struct pgpPkt pkt;
++    pgpDigParams selfsig = NULL;
++    int i = 0;
++    int alloced = 16; /* plenty for normal cases */
++    struct pgpPkt *all = xmalloc(alloced * sizeof(*all));
+     int rc = -1; /* assume failure */
++    int expect = 0;
++    int prevtag = 0;
+ 
+     while (p < pend) {
+-	if (decodePkt(p, (pend - p), &pkt))
++	struct pgpPkt *pkt = &all[i];
++	if (decodePkt(p, (pend - p), pkt))
+ 	    break;
+ 
+ 	if (digp == NULL) {
+-	    if (pkttype && pkt.tag != pkttype) {
++	    if (pkttype && pkt->tag != pkttype) {
+ 		break;
+ 	    } else {
+-		digp = xcalloc(1, sizeof(*digp));
+-		digp->tag = pkt.tag;
++		digp = pgpDigParamsNew(pkt->tag);
+ 	    }
+ 	}
+ 
+-	if (pgpPrtPkt(&pkt, digp))
++	if (expect) {
++	    if (pkt->tag != expect)
++		break;
++	    selfsig = pgpDigParamsNew(pkt->tag);
++	}
++
++	if (pgpPrtPkt(pkt, selfsig ? selfsig : digp))
+ 	    break;
+ 
+-	p += (pkt.body - pkt.head) + pkt.blen;
++	if (selfsig) {
++	    /* subkeys must be followed by binding signature */
++	    if (prevtag == PGPTAG_PUBLIC_SUBKEY) {
++		if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
++		    break;
++	    }
++
++	    int xx = pgpVerifySelf(digp, selfsig, all, i);
++
++	    selfsig = pgpDigParamsFree(selfsig);
++	    if (xx)
++		break;
++	    expect = 0;
++	}
++
++	if (pkt->tag == PGPTAG_PUBLIC_SUBKEY)
++	    expect = PGPTAG_SIGNATURE;
++	prevtag = pkt->tag;
++
++	i++;
++	p += (pkt->body - pkt->head) + pkt->blen;
++	if (pkttype == PGPTAG_SIGNATURE)
++	    break;
++
++	if (alloced <= i) {
++	    alloced *= 2;
++	    all = xrealloc(all, alloced * sizeof(*all));
++	}
+     }
+ 
+-    rc = (digp && (p == pend)) ? 0 : -1;
++    rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
+ 
++    free(all);
+     if (ret && rc == 0) {
+ 	*ret = digp;
+     } else {
+@@ -1105,8 +1195,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/tests/Makefile.am b/tests/Makefile.am
+index f742a9e1d..328234278 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -107,6 +107,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/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
+ EXTRA_DIST += data/macros.debug
+ EXTRA_DIST += data/SOURCES/foo.c
+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 000000000..aea00f9d7
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-badbind.asc
+@@ -0,0 +1,25 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
+++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
++=WCfs
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/data/keys/CVE-2021-3521-nosubsig-last.asc b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
+new file mode 100644
+index 000000000..aea00f9d7
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
+@@ -0,0 +1,25 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
+++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
++=WCfs
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/data/keys/CVE-2021-3521-nosubsig.asc b/tests/data/keys/CVE-2021-3521-nosubsig.asc
+new file mode 100644
+index 000000000..3a2e7417f
+--- /dev/null
++++ b/tests/data/keys/CVE-2021-3521-nosubsig.asc
+@@ -0,0 +1,37 @@
++-----BEGIN PGP PUBLIC KEY BLOCK-----
++Version: rpm-4.17.90 (NSS-3)
++
++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
++E4XX4jtDmdZPreZALsiB
++=rRop
++-----END PGP PUBLIC KEY BLOCK-----
++
+diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
+index e1a3ab062..705fc5870 100644
+--- a/tests/rpmsigdig.at
++++ b/tests/rpmsigdig.at
+@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
+ [])
+ AT_CLEANUP
+ 
++AT_SETUP([rpmkeys --import invalid keys])
++AT_KEYWORDS([rpmkeys import])
++RPMDB_INIT
++
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.]
++)
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.]
++)
++
++AT_CHECK([
++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc
++],
++[1],
++[],
++[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.]
++)
++AT_CLEANUP
++
+ # ------------------------------
+ # Test pre-built package verification
+ AT_SETUP([rpmkeys -K <signed> 1])
+-- 
+2.33.1
+
diff --git a/rpm.spec b/rpm.spec
index a383e91..9da035d 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -32,7 +32,7 @@
 
 %global rpmver 4.16.1.3
 #global snapver rc1
-%global rel 7
+%global rel 8
 %global sover 9
 
 %global srcver %{rpmver}%{?snapver:-%{snapver}}
@@ -72,6 +72,11 @@ Patch100: rpm-4.16.1.3-imp-covscan-fixes.patch
 Patch101: rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch
 Patch102: rpm-4.16.1.3-add-fapolicyd-plugin.patch
 Patch103: rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch
+Patch104: rpm-4.16.1.3-support-bdb-hash-v8.patch
+Patch105: rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch
+Patch106: rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch
+Patch107: rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch
+Patch108: rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch
 
 # These are not yet upstream
 Patch906: rpm-4.7.1-geode-i686.patch
@@ -368,6 +373,7 @@ done;
     --with-cap \
     --with-acl \
     %{?with_ndb: --enable-ndb} \
+    %{!?with_libarchive: --without-archive} \
     %{?with_libimaevm: --with-imaevm} \
     %{?with_zstd: --enable-zstd} \
     %{?with_sqlite: --enable-sqlite} \
@@ -461,7 +467,9 @@ fi
 %attr(0644, root, root) %ghost /var/lib/rpm/.*.lock
 
 %{_bindir}/rpm
+%if %{with libarchive}
 %{_bindir}/rpm2archive
+%endif
 %{_bindir}/rpm2cpio
 %{_bindir}/rpmdb
 %{_bindir}/rpmkeys
@@ -471,7 +479,9 @@ fi
 %{_mandir}/man8/rpm.8*
 %{_mandir}/man8/rpmdb.8*
 %{_mandir}/man8/rpmkeys.8*
+%if %{with libarchive}
 %{_mandir}/man8/rpm2archive.8*
+%endif
 %{_mandir}/man8/rpm2cpio.8*
 %{_mandir}/man8/rpm-misc.8*
 %{_mandir}/man8/rpm-plugins.8*
@@ -596,6 +606,16 @@ fi
 %doc doc/librpm/html/*
 
 %changelog
+* Thu Dec 09 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-8
+- Support hash v8 databases from BDB < 4.6 (#1965147)
+- Ensure ELF files get stripped when debuginfo is disabled (#1999009)
+- Actually honor libarchive bcond at configure time (#1999012)
+- Unbreak checking of installed rich dependencies (#2015407)
+- Rebuild against soname bump in ima-evm-utils (#2026079)
+- Fix IMA signature lengths assumed constant (#2018937)
+- Validate and require subkey binding sigs on PGP pubkeys (#1943724)
+- Fixes CVE-2021-3521
+
 * Thu Aug 19 2021 Michal Domonkos <mdomonko@redhat.com> - 4.16.1.3-7
 - Unblock signals in forked scriptlets (#1991667)