dcavalca / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone

Blame rpm-4.14.3-validate-and-require-subkey-binding-sigs.patch

James Antill ee2eaf
From 82c53e4b7f720012a391d8f6e5da9ee3c4f22bed Mon Sep 17 00:00:00 2001
James Antill ee2eaf
From: Demi Marie Obenour <demi@invisiblethingslab.com>
James Antill ee2eaf
Date: Thu, 6 May 2021 18:34:45 -0400
James Antill ee2eaf
Subject: [PATCH] Validate and require subkey binding signatures on PGP public
James Antill ee2eaf
 keys
James Antill ee2eaf
James Antill ee2eaf
All subkeys must be followed by a binding signature by the primary key
James Antill ee2eaf
as per the OpenPGP RFC, enforce the presence and validity in the parser.
James Antill ee2eaf
James Antill ee2eaf
The implementation is as kludgey as they come to work around our
James Antill ee2eaf
simple-minded parser structure without touching API, to maximise
James Antill ee2eaf
backportability. Store all the raw packets internally as we decode them
James Antill ee2eaf
to be able to access previous elements at will, needed to validate ordering
James Antill ee2eaf
and access the actual data. Add testcases for manipulated keys whose
James Antill ee2eaf
import previously would succeed.
James Antill ee2eaf
James Antill ee2eaf
Combined with:
James Antill ee2eaf
5ff86764b17f31535cb247543a90dd739076ec38
James Antill ee2eaf
b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8
James Antill ee2eaf
9f03f42e2614a68f589f9db8fe76287146522c0c
James Antill ee2eaf
b6dffb6dc5ffa2ddc389743f0507876cab341315 (mem-leak fix)
James Antill ee2eaf
ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 (use-after-free fix)
James Antill ee2eaf
James Antill ee2eaf
Fixes CVE-2021-3521.
James Antill ee2eaf
---
James Antill ee2eaf
 rpmio/rpmpgp.c                                | 122 +++++++++++++++---
James Antill ee2eaf
 sign/rpmgensig.c                              |   2 +-
James Antill ee2eaf
 tests/Makefile.am                             |   3 +
James Antill ee2eaf
 tests/data/keys/CVE-2021-3521-badbind.asc     |  25 ++++
James Antill ee2eaf
 .../data/keys/CVE-2021-3521-nosubsig-last.asc |  25 ++++
James Antill ee2eaf
 tests/data/keys/CVE-2021-3521-nosubsig.asc    |  37 ++++++
James Antill ee2eaf
 tests/rpmsigdig.at                            |  28 ++++
James Antill ee2eaf
 7 files changed, 224 insertions(+), 18 deletions(-)
James Antill ee2eaf
 create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc
James Antill ee2eaf
 create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc
James Antill ee2eaf
 create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc
James Antill ee2eaf
James Antill ee2eaf
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
James Antill ee2eaf
index 46cd0f31a..bd4992ec7 100644
James Antill ee2eaf
--- a/rpmio/rpmpgp.c
James Antill ee2eaf
+++ b/rpmio/rpmpgp.c
James Antill ee2eaf
@@ -511,7 +511,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
James Antill ee2eaf
     return NULL;
James Antill ee2eaf
 }
James Antill ee2eaf
 
James Antill ee2eaf
-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
James Antill ee2eaf
+static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo,
James Antill ee2eaf
 		const uint8_t *p, const uint8_t *h, size_t hlen,
James Antill ee2eaf
 		pgpDigParams sigp)
James Antill ee2eaf
 {
James Antill ee2eaf
@@ -524,10 +524,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
James Antill ee2eaf
 	int mpil = pgpMpiLen(p);
James Antill ee2eaf
 	if (p + mpil > pend)
James Antill ee2eaf
 	    break;
James Antill ee2eaf
-	if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
James Antill ee2eaf
-	    if (sigalg->setmpi(sigalg, i, p))
James Antill ee2eaf
-		break;
James Antill ee2eaf
-	}
James Antill ee2eaf
+	if (sigalg->setmpi(sigalg, i, p))
James Antill ee2eaf
+	    break;
James Antill ee2eaf
 	p += mpil;
James Antill ee2eaf
     }
James Antill ee2eaf
 
James Antill ee2eaf
@@ -600,7 +598,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
James Antill ee2eaf
 	}
James Antill ee2eaf
 
James Antill ee2eaf
 	p = ((uint8_t *)v) + sizeof(*v);
James Antill ee2eaf
-	rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
James Antill ee2eaf
+	rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
James Antill ee2eaf
     }	break;
James Antill ee2eaf
     case 4:
James Antill ee2eaf
     {   pgpPktSigV4 v = (pgpPktSigV4)h;
James Antill ee2eaf
@@ -658,7 +656,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
James Antill ee2eaf
 	if (p > (h + hlen))
James Antill ee2eaf
 	    return 1;
James Antill ee2eaf
 
James Antill ee2eaf
-	rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
James Antill ee2eaf
+	rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp);
James Antill ee2eaf
     }	break;
James Antill ee2eaf
     default:
James Antill ee2eaf
 	rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version);
James Antill ee2eaf
@@ -999,36 +997,127 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
James Antill ee2eaf
     return algo;
James Antill ee2eaf
 }
James Antill ee2eaf
 
James Antill ee2eaf
+static pgpDigParams pgpDigParamsNew(uint8_t tag)
James Antill ee2eaf
+{
James Antill ee2eaf
+    pgpDigParams digp = xcalloc(1, sizeof(*digp));
James Antill ee2eaf
+    digp->tag = tag;
James Antill ee2eaf
+    return digp;
James Antill ee2eaf
+}
James Antill ee2eaf
+
James Antill ee2eaf
+static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag)
James Antill ee2eaf
+{
James Antill ee2eaf
+    int rc = -1;
James Antill ee2eaf
+    if (pkt->tag == exptag) {
James Antill ee2eaf
+	uint8_t head[] = {
James Antill ee2eaf
+	    0x99,
James Antill ee2eaf
+	    (pkt->blen >> 8),
James Antill ee2eaf
+	    (pkt->blen     ),
James Antill ee2eaf
+	};
James Antill ee2eaf
+
James Antill ee2eaf
+	rpmDigestUpdate(hash, head, 3);
James Antill ee2eaf
+	rpmDigestUpdate(hash, pkt->body, pkt->blen);
James Antill ee2eaf
+	rc = 0;
James Antill ee2eaf
+    }
James Antill ee2eaf
+    return rc;
James Antill ee2eaf
+}
James Antill ee2eaf
+
James Antill ee2eaf
+static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
James Antill ee2eaf
+			const struct pgpPkt *all, int i)
James Antill ee2eaf
+{
James Antill ee2eaf
+    int rc = -1;
James Antill ee2eaf
+    DIGEST_CTX hash = NULL;
James Antill ee2eaf
+
James Antill ee2eaf
+    switch (selfsig->sigtype) {
James Antill ee2eaf
+    case PGPSIGTYPE_SUBKEY_BINDING:
James Antill ee2eaf
+	hash = rpmDigestInit(selfsig->hash_algo, 0);
James Antill ee2eaf
+	if (hash) {
James Antill ee2eaf
+	    rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY);
James Antill ee2eaf
+	    if (!rc)
James Antill ee2eaf
+		rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY);
James Antill ee2eaf
+	}
James Antill ee2eaf
+	break;
James Antill ee2eaf
+    default:
James Antill ee2eaf
+	/* ignore types we can't handle */
James Antill ee2eaf
+	rc = 0;
James Antill ee2eaf
+	break;
James Antill ee2eaf
+    }
James Antill ee2eaf
+
James Antill ee2eaf
+    if (hash && rc == 0)
James Antill ee2eaf
+	rc = pgpVerifySignature(key, selfsig, hash);
James Antill ee2eaf
+
James Antill ee2eaf
+    rpmDigestFinal(hash, NULL, NULL, 0);
James Antill ee2eaf
+
James Antill ee2eaf
+    return rc;
James Antill ee2eaf
+}
James Antill ee2eaf
+
James Antill ee2eaf
 int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
James Antill ee2eaf
 		 pgpDigParams * ret)
James Antill ee2eaf
 {
James Antill ee2eaf
     const uint8_t *p = pkts;
James Antill ee2eaf
     const uint8_t *pend = pkts + pktlen;
James Antill ee2eaf
     pgpDigParams digp = NULL;
James Antill ee2eaf
-    struct pgpPkt pkt;
James Antill ee2eaf
+    pgpDigParams selfsig = NULL;
James Antill ee2eaf
+    int i = 0;
James Antill ee2eaf
+    int alloced = 16; /* plenty for normal cases */
James Antill ee2eaf
+    struct pgpPkt *all = xmalloc(alloced * sizeof(*all));
James Antill ee2eaf
     int rc = -1; /* assume failure */
James Antill ee2eaf
+    int expect = 0;
James Antill ee2eaf
+    int prevtag = 0;
James Antill ee2eaf
 
James Antill ee2eaf
     while (p < pend) {
James Antill ee2eaf
-	if (decodePkt(p, (pend - p), &pkt))
James Antill ee2eaf
+	struct pgpPkt *pkt = &all[i];
James Antill ee2eaf
+	if (decodePkt(p, (pend - p), pkt))
James Antill ee2eaf
 	    break;
James Antill ee2eaf
 
James Antill ee2eaf
 	if (digp == NULL) {
James Antill ee2eaf
-	    if (pkttype && pkt.tag != pkttype) {
James Antill ee2eaf
+	    if (pkttype && pkt->tag != pkttype) {
James Antill ee2eaf
 		break;
James Antill ee2eaf
 	    } else {
James Antill ee2eaf
-		digp = xcalloc(1, sizeof(*digp));
James Antill ee2eaf
-		digp->tag = pkt.tag;
James Antill ee2eaf
+		digp = pgpDigParamsNew(pkt->tag);
James Antill ee2eaf
 	    }
James Antill ee2eaf
 	}
James Antill ee2eaf
 
James Antill ee2eaf
-	if (pgpPrtPkt(&pkt, digp))
James Antill ee2eaf
+	if (expect) {
James Antill ee2eaf
+	    if (pkt->tag != expect)
James Antill ee2eaf
+		break;
James Antill ee2eaf
+	    selfsig = pgpDigParamsNew(pkt->tag);
James Antill ee2eaf
+	}
James Antill ee2eaf
+
James Antill ee2eaf
+	if (pgpPrtPkt(pkt, selfsig ? selfsig : digp))
James Antill ee2eaf
 	    break;
James Antill ee2eaf
 
James Antill ee2eaf
-	p += (pkt.body - pkt.head) + pkt.blen;
James Antill ee2eaf
+	if (selfsig) {
James Antill ee2eaf
+	    /* subkeys must be followed by binding signature */
James Antill ee2eaf
+	    int xx = 1; /* assume failure */
James Antill ee2eaf
+
James Antill ee2eaf
+	    if (!(prevtag == PGPTAG_PUBLIC_SUBKEY &&
James Antill ee2eaf
+		  selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING))
James Antill ee2eaf
+		xx = pgpVerifySelf(digp, selfsig, all, i);
James Antill ee2eaf
+
James Antill ee2eaf
+	    selfsig = pgpDigParamsFree(selfsig);
James Antill ee2eaf
+	    if (xx)
James Antill ee2eaf
+		break;
James Antill ee2eaf
+	    expect = 0;
James Antill ee2eaf
+	}
James Antill ee2eaf
+
James Antill ee2eaf
+	if (pkt->tag == PGPTAG_PUBLIC_SUBKEY)
James Antill ee2eaf
+	    expect = PGPTAG_SIGNATURE;
James Antill ee2eaf
+	prevtag = pkt->tag;
James Antill ee2eaf
+
James Antill ee2eaf
+	i++;
James Antill ee2eaf
+	p += (pkt->body - pkt->head) + pkt->blen;
James Antill ee2eaf
+	if (pkttype == PGPTAG_SIGNATURE)
James Antill ee2eaf
+	    break;
James Antill ee2eaf
+
James Antill ee2eaf
+	if (alloced <= i) {
James Antill ee2eaf
+	    alloced *= 2;
James Antill ee2eaf
+	    all = xrealloc(all, alloced * sizeof(*all));
James Antill ee2eaf
+	}
James Antill ee2eaf
     }
James Antill ee2eaf
 
James Antill ee2eaf
-    rc = (digp && (p == pend)) ? 0 : -1;
James Antill ee2eaf
+    rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
James Antill ee2eaf
 
James Antill ee2eaf
+    free(all);
James Antill ee2eaf
     if (ret && rc == 0) {
James Antill ee2eaf
 	*ret = digp;
James Antill ee2eaf
     } else {
James Antill ee2eaf
@@ -1063,8 +1152,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
James Antill ee2eaf
 		digps = xrealloc(digps, alloced * sizeof(*digps));
James Antill ee2eaf
 	    }
James Antill ee2eaf
 
James Antill ee2eaf
-	    digps[count] = xcalloc(1, sizeof(**digps));
James Antill ee2eaf
-	    digps[count]->tag = PGPTAG_PUBLIC_SUBKEY;
James Antill ee2eaf
+	    digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY);
James Antill ee2eaf
 	    /* Copy UID from main key to subkey */
James Antill ee2eaf
 	    digps[count]->userid = xstrdup(mainkey->userid);
James Antill ee2eaf
 
James Antill ee2eaf
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
James Antill ee2eaf
index 771d01098..b33fe996c 100644
James Antill ee2eaf
--- a/sign/rpmgensig.c
James Antill ee2eaf
+++ b/sign/rpmgensig.c
James Antill ee2eaf
@@ -409,7 +409,7 @@ static int haveSignature(rpmtd sigtd, Header h)
James Antill ee2eaf
 	pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2;;
James Antill ee2eaf
 	if (pgpDigParamsCmp(sig1, sig2) == 0)
James Antill ee2eaf
 	    rc = 1;
James Antill ee2eaf
-	pgpDigParamsFree(sig2);
James Antill ee2eaf
+	sig2 = pgpDigParamsFree(sig2);
James Antill ee2eaf
     }
James Antill ee2eaf
     pgpDigParamsFree(sig1);
James Antill ee2eaf
     rpmtdFreeData(&oldtd);
James Antill ee2eaf
diff --git a/tests/Makefile.am b/tests/Makefile.am
James Antill ee2eaf
index 5f5207e56..309347262 100644
James Antill ee2eaf
--- a/tests/Makefile.am
James Antill ee2eaf
+++ b/tests/Makefile.am
James Antill ee2eaf
@@ -87,6 +87,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec
James Antill ee2eaf
 EXTRA_DIST += data/SPECS/hello-cd.spec
James Antill ee2eaf
 EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.pub
James Antill ee2eaf
 EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.secret
James Antill ee2eaf
+EXTRA_DIST += data/keys/CVE-2021-3521-badbind.asc
James Antill ee2eaf
+EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig.asc
James Antill ee2eaf
+EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig-last.asc
James Antill ee2eaf
 EXTRA_DIST += data/macros.testfile
James Antill ee2eaf
 
James Antill ee2eaf
 # testsuite voodoo
James Antill ee2eaf
diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc
James Antill ee2eaf
new file mode 100644
James Antill ee2eaf
index 000000000..aea00f9d7
James Antill ee2eaf
--- /dev/null
James Antill ee2eaf
+++ b/tests/data/keys/CVE-2021-3521-badbind.asc
James Antill ee2eaf
@@ -0,0 +1,25 @@
James Antill ee2eaf
+-----BEGIN PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+Version: rpm-4.17.90 (NSS-3)
James Antill ee2eaf
+
James Antill ee2eaf
+mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
James Antill ee2eaf
+HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
James Antill ee2eaf
+91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
James Antill ee2eaf
+eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
James Antill ee2eaf
+7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
James Antill ee2eaf
+1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
James Antill ee2eaf
+c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
James Antill ee2eaf
+CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
James Antill ee2eaf
+Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
James Antill ee2eaf
+BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
James Antill ee2eaf
+XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
James Antill ee2eaf
+fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
James Antill ee2eaf
++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
James Antill ee2eaf
+BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
James Antill ee2eaf
+zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
James Antill ee2eaf
+iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
James Antill ee2eaf
+Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
James Antill ee2eaf
+KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
James Antill ee2eaf
+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
James Antill ee2eaf
+=WCfs
James Antill ee2eaf
+-----END PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+
James Antill ee2eaf
diff --git a/tests/data/keys/CVE-2021-3521-nosubsig-last.asc b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
James Antill ee2eaf
new file mode 100644
James Antill ee2eaf
index 000000000..aea00f9d7
James Antill ee2eaf
--- /dev/null
James Antill ee2eaf
+++ b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc
James Antill ee2eaf
@@ -0,0 +1,25 @@
James Antill ee2eaf
+-----BEGIN PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+Version: rpm-4.17.90 (NSS-3)
James Antill ee2eaf
+
James Antill ee2eaf
+mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
James Antill ee2eaf
+HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
James Antill ee2eaf
+91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
James Antill ee2eaf
+eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
James Antill ee2eaf
+7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
James Antill ee2eaf
+1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
James Antill ee2eaf
+c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
James Antill ee2eaf
+CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
James Antill ee2eaf
+Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
James Antill ee2eaf
+BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
James Antill ee2eaf
+XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
James Antill ee2eaf
+fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
James Antill ee2eaf
++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
James Antill ee2eaf
+BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
James Antill ee2eaf
+zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
James Antill ee2eaf
+iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
James Antill ee2eaf
+Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
James Antill ee2eaf
+KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
James Antill ee2eaf
+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE=
James Antill ee2eaf
+=WCfs
James Antill ee2eaf
+-----END PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+
James Antill ee2eaf
diff --git a/tests/data/keys/CVE-2021-3521-nosubsig.asc b/tests/data/keys/CVE-2021-3521-nosubsig.asc
James Antill ee2eaf
new file mode 100644
James Antill ee2eaf
index 000000000..3a2e7417f
James Antill ee2eaf
--- /dev/null
James Antill ee2eaf
+++ b/tests/data/keys/CVE-2021-3521-nosubsig.asc
James Antill ee2eaf
@@ -0,0 +1,37 @@
James Antill ee2eaf
+-----BEGIN PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+Version: rpm-4.17.90 (NSS-3)
James Antill ee2eaf
+
James Antill ee2eaf
+mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g
James Antill ee2eaf
+HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY
James Antill ee2eaf
+91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8
James Antill ee2eaf
+eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas
James Antill ee2eaf
+7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ
James Antill ee2eaf
+1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl
James Antill ee2eaf
+c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK
James Antill ee2eaf
+CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf
James Antill ee2eaf
+Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB
James Antill ee2eaf
+BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr
James Antill ee2eaf
+XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX
James Antill ee2eaf
+fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq
James Antill ee2eaf
++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN
James Antill ee2eaf
+BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY
James Antill ee2eaf
+zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz
James Antill ee2eaf
+iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6
James Antill ee2eaf
+Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c
James Antill ee2eaf
+KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m
James Antill ee2eaf
+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAG5AQ0EWOY5GAEIAKT68NmshdC4
James Antill ee2eaf
+VcRhOhlXBvZq23NtskkKoPvW+ZlMuxbRDG48pGBtxhjOngriVUGceEWsXww5Q7En
James Antill ee2eaf
+uRBYglkxkW34ENym0Ji6tsPYfhbbG+dZWKIL4vMIzPOIwlPrXrm558vgkdMM/ELZ
James Antill ee2eaf
+8WIz3KtzvYubKUk2Qz+96lPXbwnlC/SBFRpBseJC5LoOb/5ZGdR/HeLz1JXiacHF
James Antill ee2eaf
+v9Nr3cZWqg5yJbDNZKfASdZgC85v3kkvhTtzknl//5wqdAMexbuwiIh2xyxbO+B/
James Antill ee2eaf
+qqzZFrVmu3sV2Tj5lLZ/9p1qAuEM7ULbixd/ld8yTmYvQ4bBlKv2bmzXtVfF+ymB
James Antill ee2eaf
+Tm6BzyQEl/MAEQEAAYkBHwQYAQgACQUCWOY5GAIbDAAKCRBDRFkeGWTF/PANB/9j
James Antill ee2eaf
+mifmj6z/EPe0PJFhrpISt9PjiUQCt0IPtiL5zKAkWjHePIzyi+0kCTBF6DDLFxos
James Antill ee2eaf
+3vN4bWnVKT1kBhZAQlPqpJTg+m74JUYeDGCdNx9SK7oRllATqyu+5rncgxjWVPnQ
James Antill ee2eaf
+zu/HRPlWJwcVFYEVXYL8xzfantwQTqefjmcRmBRdA2XJITK+hGWwAmrqAWx+q5xX
James Antill ee2eaf
+Pa8wkNMxVzNS2rUKO9SoVuJ/wlUvfoShkJ/VJ5HDp3qzUqncADfdGN35TDzscngQ
James Antill ee2eaf
+gHvnMwVBfYfSCABV1hNByoZcc/kxkrWMmsd/EnIyLd1Q1baKqc3cEDuC6E6/o4yJ
James Antill ee2eaf
+E4XX4jtDmdZPreZALsiB
James Antill ee2eaf
+=rRop
James Antill ee2eaf
+-----END PGP PUBLIC KEY BLOCK-----
James Antill ee2eaf
+
James Antill ee2eaf
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
James Antill ee2eaf
index 09fcdd525..a74f400ae 100644
James Antill ee2eaf
--- a/tests/rpmsigdig.at
James Antill ee2eaf
+++ b/tests/rpmsigdig.at
James Antill ee2eaf
@@ -212,6 +212,34 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ==
James Antill ee2eaf
 [])
James Antill ee2eaf
 AT_CLEANUP
James Antill ee2eaf
 
James Antill ee2eaf
+AT_SETUP([rpmkeys --import invalid keys])
James Antill ee2eaf
+AT_KEYWORDS([rpmkeys import])
James Antill ee2eaf
+RPMDB_INIT
James Antill ee2eaf
+
James Antill ee2eaf
+AT_CHECK([
James Antill ee2eaf
+runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc
James Antill ee2eaf
+],
James Antill ee2eaf
+[1],
James Antill ee2eaf
+[],
James Antill ee2eaf
+[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.]
James Antill ee2eaf
+)
James Antill ee2eaf
+AT_CHECK([
James Antill ee2eaf
+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc
James Antill ee2eaf
+],
James Antill ee2eaf
+[1],
James Antill ee2eaf
+[],
James Antill ee2eaf
+[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.]
James Antill ee2eaf
+)
James Antill ee2eaf
+
James Antill ee2eaf
+AT_CHECK([
James Antill ee2eaf
+runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc
James Antill ee2eaf
+],
James Antill ee2eaf
+[1],
James Antill ee2eaf
+[],
James Antill ee2eaf
+[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.]
James Antill ee2eaf
+)
James Antill ee2eaf
+AT_CLEANUP
James Antill ee2eaf
+
James Antill ee2eaf
 # ------------------------------
James Antill ee2eaf
 # Test pre-built package verification
James Antill ee2eaf
 AT_SETUP([rpmkeys -K <signed> 1])
James Antill ee2eaf
-- 
James Antill ee2eaf
2.34.1
James Antill ee2eaf