From a9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305 Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Sun, 27 Mar 2022 12:49:07 -0400 Subject: [PATCH] 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. --- rpmio/rpmpgp.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- tests/rpmsigdig.at | 2 -- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c index 66837b1..22ac9c8 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c @@ -1133,6 +1133,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; +} + int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, pgpDigParams * ret) { @@ -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 5d781d8..ab9b473 100644 --- a/tests/rpmsigdig.at +++ b/tests/rpmsigdig.at @@ -247,8 +247,6 @@ UNW2iqnN3BA7guhOv6OMiROF1+I7Q5nWT63mQC7IgQ== gpg(rpm.org RSA testkey ) = 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 -- 1.8.3.1