chantra / rpms / rpm

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