105 lines
3.2 KiB
Diff
105 lines
3.2 KiB
Diff
|
|
From a9cca032a2b7c0c6bcacc6ab4ecd25c95cc75305 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Demi Marie Obenour <demi@invisiblethingslab.com>
|
||
|
|
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 <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
|
||
|
|
--
|
||
|
|
1.8.3.1
|
||
|
|
|