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