summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/header.c48
-rw-r--r--lib/header_internal.h2
-rw-r--r--lib/package.c98
-rw-r--r--lib/rpmchecksig.c3
-rw-r--r--rpmio/rpmpgp.c108
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/data/keys/CVE-2021-3521-badbind.asc25
-rwxr-xr-xtests/data/keys/CVE-2021-3521-nosubsig-last.asc25
-rwxr-xr-xtests/data/keys/CVE-2021-3521-nosubsig.asc37
-rw-r--r--tests/rpmsigdig.at28
10 files changed, 296 insertions, 81 deletions
diff --git a/lib/header.c b/lib/header.c
index 0f6efe485..0d50f0daf 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -11,6 +11,7 @@
#include "system.h"
#include <netdb.h>
#include <errno.h>
+#include <inttypes.h>
#include <rpm/rpmtypes.h>
#include <rpm/rpmstring.h>
#include "lib/header_internal.h"
@@ -1851,6 +1852,25 @@ exit:
return rc;
}
+
+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
+ char **emsg) {
+ uint32_t il_max = HEADER_TAGS_MAX;
+ uint32_t dl_max = HEADER_DATA_MAX;
+ if (regionTag == RPMTAG_HEADERSIGNATURES) {
+ il_max = 32;
+ dl_max = 64 * 1024 * 1024;
+ }
+ if (hdrchkRange(il_max, il)) {
+ rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
+ return RPMRC_FAIL;
+ }
+ if (hdrchkRange(dl_max, dl)) {
+ rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
+ return RPMRC_FAIL;
+ }
+ return RPMRC_OK;
+}
rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
{
int32_t block[4];
@@ -1863,13 +1883,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
size_t nb;
rpmRC rc = RPMRC_FAIL; /* assume failure */
int xx;
- int32_t il_max = HEADER_TAGS_MAX;
- int32_t dl_max = HEADER_DATA_MAX;
-
- if (regionTag == RPMTAG_HEADERSIGNATURES) {
- il_max = 32;
- dl_max = 8192;
- }
memset(block, 0, sizeof(block));
if ((xx = Freadall(fd, bs, blen)) != blen) {
@@ -1882,15 +1895,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
goto exit;
}
il = ntohl(block[2]);
- if (hdrchkRange(il_max, il)) {
- rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
- goto exit;
- }
dl = ntohl(block[3]);
- if (hdrchkRange(dl_max, dl)) {
- rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
+ if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
goto exit;
- }
nb = (il * sizeof(struct entryInfo_s)) + dl;
uc = sizeof(il) + sizeof(dl) + nb;
@@ -1934,11 +1941,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
struct hdrblob_s *blob, char **emsg)
{
rpmRC rc = RPMRC_FAIL;
-
memset(blob, 0, sizeof(*blob));
+ if (uc && uc < 8) {
+ rasprintf(emsg, _("hdr length: BAD"));
+ goto exit;
+ }
+
blob->ei = (int32_t *) uh; /* discards const */
- blob->il = ntohl(blob->ei[0]);
- blob->dl = ntohl(blob->ei[1]);
+ blob->il = ntohl((uint32_t)(blob->ei[0]));
+ blob->dl = ntohl((uint32_t)(blob->ei[1]));
+ if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
+ goto exit;
+
blob->pe = (entryInfo) &(blob->ei[2]);
blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
(blob->il * sizeof(*blob->pe)) + blob->dl;
diff --git a/lib/header_internal.h b/lib/header_internal.h
index 81c8c1e9d..76b7ed5a7 100644
--- a/lib/header_internal.h
+++ b/lib/header_internal.h
@@ -88,7 +88,7 @@ ssize_t Freadall(FD_t fd, void * buf, ssize_t size);
/* XXX here only temporarily */
RPM_GNUC_INTERNAL
-void headerMergeLegacySigs(Header h, Header sigh);
+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg);
RPM_GNUC_INTERNAL
void applyRetrofits(Header h, int leadtype);
RPM_GNUC_INTERNAL
diff --git a/lib/package.c b/lib/package.c
index 1d9e9e138..74cd9f479 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -22,75 +22,65 @@
#include "debug.h"
+
+struct taglate_s {
+ rpmTagVal stag;
+ rpmTagVal xtag;
+ rpm_count_t count;
+} const xlateTags[] = {
+ { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1 },
+ { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0 },
+ { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16 },
+ { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0 },
+ /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0 }, */ /* long obsolete, dont use */
+ { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1 },
+ { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1 },
+ { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1 },
+ { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0 },
+ { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0 },
+ { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1 },
+ { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1 },
+ { 0 }
+};
/** \ingroup header
* Translate and merge legacy signature tags into header.
* @param h header (dest)
* @param sigh signature header (src)
*/
-void headerMergeLegacySigs(Header h, Header sigh)
+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
{
- HeaderIterator hi;
+ const struct taglate_s *xl;
struct rpmtd_s td;
- hi = headerInitIterator(sigh);
- for (; headerNext(hi, &td); rpmtdFreeData(&td))
- {
- switch (td.tag) {
- /* XXX Translate legacy signature tag values. */
- case RPMSIGTAG_SIZE:
- td.tag = RPMTAG_SIGSIZE;
- break;
- case RPMSIGTAG_PGP:
- td.tag = RPMTAG_SIGPGP;
- break;
- case RPMSIGTAG_MD5:
- td.tag = RPMTAG_SIGMD5;
- break;
- case RPMSIGTAG_GPG:
- td.tag = RPMTAG_SIGGPG;
- break;
- case RPMSIGTAG_PGP5:
- td.tag = RPMTAG_SIGPGP5;
+ rpmtdReset(&td);
+ for (xl = xlateTags; xl->stag; xl++) {
+ /* There mustn't be one in the main header */
+ if (headerIsEntry(h, xl->xtag))
break;
- case RPMSIGTAG_PAYLOADSIZE:
- td.tag = RPMTAG_ARCHIVESIZE;
- break;
- case RPMSIGTAG_SHA1:
- case RPMSIGTAG_SHA256:
- case RPMSIGTAG_DSA:
- case RPMSIGTAG_RSA:
- default:
- if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
- continue;
- break;
- }
- if (!headerIsEntry(h, td.tag)) {
- switch (td.type) {
- case RPM_NULL_TYPE:
- continue;
+ if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
+ /* Translate legacy tags */
+ if (xl->stag != xl->xtag)
+ td.tag = xl->xtag;
+ /* Ensure type and tag size match expectations */
+ if (td.type != rpmTagGetTagType(td.tag))
break;
- case RPM_CHAR_TYPE:
- case RPM_INT8_TYPE:
- case RPM_INT16_TYPE:
- case RPM_INT32_TYPE:
- case RPM_INT64_TYPE:
- if (td.count != 1)
- continue;
+ if (td.count < 1 || td.count > 16*1024*1024)
break;
- case RPM_STRING_TYPE:
- case RPM_BIN_TYPE:
- if (td.count >= 16*1024)
- continue;
+ if (xl->count && td.count != xl->count)
break;
- case RPM_STRING_ARRAY_TYPE:
- case RPM_I18NSTRING_TYPE:
- continue;
+ if (!headerPut(h, &td, HEADERPUT_DEFAULT))
break;
- }
- (void) headerPut(h, &td, HEADERPUT_DEFAULT);
+ rpmtdFreeData(&td);
}
}
- headerFreeIterator(hi);
+ rpmtdFreeData(&td);
+
+ if (xl->stag) {
+ rasprintf(msg, "invalid signature tag %s (%d)",
+ rpmTagGetName(xl->xtag), xl->xtag);
+ }
+
+ return xl->stag;
}
/**
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
index 196bb1ccb..26a81efab 100644
--- a/lib/rpmchecksig.c
+++ b/lib/rpmchecksig.c
@@ -226,7 +226,8 @@ rpmRC rpmpkgRead(rpmPlugins plugins, rpmKeyring keyring, rpmVSFlags flags, FD_t
goto exit;
/* Append (and remap) signature tags to the metadata. */
- headerMergeLegacySigs(h, sigh);
+ if (headerMergeLegacySigs(h, sigh, &msg))
+ goto exit;
applyRetrofits(h, leadtype);
/* Bump reference count for return. */
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index 061751a4d..15cce2275 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -999,36 +999,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 {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f2bdb7bae..bd5d4d71d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -86,6 +86,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
# testsuite voodoo
AUTOTEST = $(AUTOM4TE) --language=autotest
diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc
new file mode 100755
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 100755
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 100755
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)
+
+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
+L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAG5AQ0EWOY5GAEIAKT68NmshdC4
+VcRhOhlXBvZq23NtskkKoPvW+ZlMuxbRDG48pGBtxhjOngriVUGceEWsXww5Q7En
+uRBYglkxkW34ENym0Ji6tsPYfhbbG+dZWKIL4vMIzPOIwlPrXrm558vgkdMM/ELZ
+8WIz3KtzvYubKUk2Qz+96lPXbwnlC/SBFRpBseJC5LoOb/5ZGdR/HeLz1JXiacHF
+v9Nr3cZWqg5yJbDNZKfASdZgC85v3kkvhTtzknl//5wqdAMexbuwiIh2xyxbO+B/
+qqzZFrVmu3sV2Tj5lLZ/9p1qAuEM7ULbixd/ld8yTmYvQ4bBlKv2bmzXtVfF+ymB
+Tm6BzyQEl/MAEQEAAYkBHwQYAQgACQUCWOY5GAIbDAAKCRBDRFkeGWTF/PANB/9j
+mifmj6z/EPe0PJFhrpISt9PjiUQCt0IPtiL5zKAkWjHePIzyi+0kCTBF6DDLFxos
+3vN4bWnVKT1kBhZAQlPqpJTg+m74JUYeDGCdNx9SK7oRllATqyu+5rncgxjWVPnQ
+zu/HRPlWJwcVFYEVXYL8xzfantwQTqefjmcRmBRdA2XJITK+hGWwAmrqAWx+q5xX
+Pa8wkNMxVzNS2rUKO9SoVuJ/wlUvfoShkJ/VJ5HDp3qzUqncADfdGN35TDzscngQ
+gHvnMwVBfYfSCABV1hNByoZcc/kxkrWMmsd/EnIyLd1Q1baKqc3cEDuC6E6/o4yJ
+E4XX4jtDmdZPreZALsiB
+=rRop
+-----END PGP PUBLIC KEY BLOCK-----
+
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index 9df3c5bd8..69382999f 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -191,6 +191,34 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ==
[])
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])