alexk / rpms / rpm

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