diff options
author | Demi Marie Obenour <demi@invisiblethingslab.com> | 2022-03-27 12:49:07 -0400 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2022-03-31 09:52:50 +0300 |
commit | a9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305 (patch) | |
tree | 2491ab779b5dab2f77d8c60665c59f62dff45708 | |
parent | 598a771d8b4f4f480d4990ccf59b978d537201dd (diff) | |
download | rpm-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.c | 48 | ||||
-rw-r--r-- | tests/rpmsigdig.at | 2 |
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 |