summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDemi Marie Obenour <demi@invisiblethingslab.com>2022-03-27 12:49:07 -0400
committerPanu Matilainen <pmatilai@redhat.com>2022-03-31 09:52:50 +0300
commita9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305 (patch)
tree2491ab779b5dab2f77d8c60665c59f62dff45708
parent598a771d8b4f4f480d4990ccf59b978d537201dd (diff)
downloadrpm-a9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305.tar.gz
Ignore subkeys that cannot be used for signing
This ensures that a signature is only accepted if the subkey that made it is actually allowed to sign. Test 265 verifies that RPM ignores subkeys that cannot sign. A subkey is considered to be capable of signing if, and only if, its subkey binding signature has a hashed key flags subpacket that contains the flag 0x02. RFC4880 requires that the subkey binding signature be v4, which this requirement enforces implicitly. RFC4880 also requires that primary key binding signatures be present and checked. This is not yet implemented, but may be implemented later. Fixes #1911.
-rw-r--r--rpmio/rpmpgp.c48
-rw-r--r--tests/rpmsigdig.at2
2 files changed, 47 insertions, 3 deletions
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index 66837b18f..22ac9c816 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -1117,6 +1117,31 @@ static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
return rc;
}
+static int parseSubkeySig(const struct pgpPkt *pkt, uint8_t tag,
+ pgpDigParams *params_p) {
+ pgpDigParams params = *params_p = NULL; /* assume failure */
+
+ if (pkt->tag != PGPTAG_SIGNATURE)
+ goto fail;
+
+ params = pgpDigParamsNew(tag);
+
+ if (pgpPrtSig(tag, pkt->body, pkt->blen, params))
+ goto fail;
+
+ if (params->sigtype != PGPSIGTYPE_SUBKEY_BINDING &&
+ params->sigtype != PGPSIGTYPE_SUBKEY_REVOKE)
+ {
+ goto fail;
+ }
+
+ *params_p = params;
+ return 0;
+fail:
+ pgpDigParamsFree(params);
+ return -1;
+}
+
static const size_t RPM_MAX_OPENPGP_BYTES = 65535; /* max number of bytes in a key */
int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
@@ -1238,7 +1263,28 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
pgpDigParamsFree(digps[count]);
continue;
}
- count++;
+
+ pgpDigParams subkey_sig = NULL;
+ if (decodePkt(p, pend - p, &pkt) ||
+ parseSubkeySig(&pkt, 0, &subkey_sig))
+ {
+ pgpDigParamsFree(digps[count]);
+ break;
+ }
+
+ /* Is the subkey revoked or incapable of signing? */
+ int ignore = subkey_sig->sigtype != PGPSIGTYPE_SUBKEY_BINDING ||
+ !((subkey_sig->saved & PGPDIG_SIG_HAS_KEY_FLAGS) &&
+ (subkey_sig->key_flags & 0x02));
+ if (ignore) {
+ pgpDigParamsFree(digps[count]);
+ } else {
+ digps[count]->key_flags = subkey_sig->key_flags;
+ digps[count]->saved |= PGPDIG_SIG_HAS_KEY_FLAGS;
+ count++;
+ }
+ p += (pkt.body - pkt.head) + pkt.blen;
+ pgpDigParamsFree(subkey_sig);
}
}
rc = (p == pend) ? 0 : -1;
diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at
index 5d781d89f..ab9b47393 100644
--- a/tests/rpmsigdig.at
+++ b/tests/rpmsigdig.at
@@ -247,8 +247,6 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ==
gpg(rpm.org RSA testkey <rsa@rpm.org>) = 4:4344591e1964c5fc-58e63918
gpg(1964c5fc) = 4:4344591e1964c5fc-58e63918
gpg(4344591e1964c5fc) = 4:4344591e1964c5fc-58e63918
-gpg(f00650f8) = 4:185e6146f00650f8-58e63918
-gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918
],
[])
AT_CLEANUP