File verifybindingsig.diff of Package python-rpm
--- rpmio/digest.h.orig 2024-04-29 09:11:59.251170068 +0000
+++ rpmio/digest.h 2024-04-29 10:54:13.168416920 +0000
@@ -33,12 +33,13 @@ struct pgpDigParams_s {
uint8_t hash_algo;
uint8_t sigtype;
- uint8_t hashlen;
+ uint32_t hashlen;
uint8_t signhash16[2];
pgpKeyID_t signid;
uint8_t saved;
#define PGPDIG_SAVED_TIME (1 << 0)
#define PGPDIG_SAVED_ID (1 << 1)
+ uint8_t key_flags;
pgpDigAlg alg;
};
--- rpmio/rpmpgp.c.orig 2024-04-29 09:11:10.259240666 +0000
+++ rpmio/rpmpgp.c 2024-04-29 09:36:15.612510965 +0000
@@ -16,6 +16,8 @@
#include "debug.h"
+static rpmRC pgpVerifySignatureRaw(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx);
+
static int _print = 0;
/** \ingroup rpmio
@@ -412,7 +414,7 @@ static int pgpVersion(const uint8_t *h,
}
static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
- pgpDigParams _digp)
+ pgpDigParams _digp, int hashed)
{
const uint8_t *p = h;
size_t plen = 0, i;
@@ -449,6 +451,8 @@ static int pgpPrtSubType(const uint8_t *
pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
break;
case PGPSUBTYPE_SIG_CREATE_TIME:
+ if (!hashed)
+ break;
impl = *p;
if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
@@ -478,8 +482,15 @@ static int pgpPrtSubType(const uint8_t *
pgpPrtHex("", p+1, plen-1);
break;
- case PGPSUBTYPE_PRIMARY_USERID:
case PGPSUBTYPE_KEY_FLAGS:
+ if (!hashed)
+ break;
+ impl = *p; /* accept critical packet */
+ _digp->key_flags = plen >= 2 ? p[1] : 0;
+ pgpPrtHex("", p+1, plen-1);
+ break;
+
+ case PGPSUBTYPE_PRIMARY_USERID:
case PGPSUBTYPE_EMBEDDED_SIG:
impl = *p; /* accept critical packet */
pgpPrtHex("", p+1, plen-1);
@@ -550,7 +561,7 @@ static int pgpPrtSigParams(pgpTag tag, u
int mpil = pgpMpiLen(p);
if (pend - p < mpil)
break;
- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
+ if (sigp->tag == PGPTAG_SIGNATURE) {
if (sigalg->setmpi(sigalg, i, p))
break;
}
@@ -657,7 +668,7 @@ static int pgpPrtSig(pgpTag tag, const u
_digp->hashlen = sizeof(*v) + plen;
_digp->hash = memcpy(xmalloc(_digp->hashlen), v, _digp->hashlen);
}
- if (pgpPrtSubType(p, plen, v->sigtype, _digp))
+ if (pgpPrtSubType(p, plen, v->sigtype, _digp, 1))
return 1;
p += plen;
@@ -668,7 +679,7 @@ static int pgpPrtSig(pgpTag tag, const u
if ((p + plen) > hend)
return 1;
- if (pgpPrtSubType(p, plen, v->sigtype, _digp))
+ if (pgpPrtSubType(p, plen, v->sigtype, _digp, 0))
return 1;
p += plen;
@@ -1068,13 +1079,52 @@ unsigned int pgpDigParamsAlgo(pgpDigPara
return algo;
}
+static void hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt)
+{
+ uint8_t head[] = {
+ 0x99,
+ (pkt->blen >> 8),
+ (pkt->blen )
+ };
+ rpmDigestUpdate(hash, head, 3);
+ rpmDigestUpdate(hash, pkt->body, pkt->blen);
+}
+
+static int verifySubkeyBindingSignature(pgpDigParams digp, struct pgpPkt *mainpkt, struct pgpPkt *subkeypkt, struct pgpPkt *sigpkt)
+{
+ int rc = -1; /* assume failure */
+ pgpDigParams sigdigp = NULL;
+ DIGEST_CTX hash = NULL;
+
+ if (mainpkt->tag != PGPTAG_PUBLIC_KEY || subkeypkt->tag != PGPTAG_PUBLIC_SUBKEY || sigpkt->tag != PGPTAG_SIGNATURE)
+ goto exit;
+ sigdigp = xcalloc(1, sizeof(*sigdigp));
+ sigdigp->tag = PGPTAG_SIGNATURE;
+ if (pgpPrtPkt(sigpkt, sigdigp))
+ goto exit;
+ if (sigdigp->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
+ goto exit;
+ hash = rpmDigestInit(sigdigp->hash_algo, 0);
+ if (!hash)
+ goto exit;
+ hashKey(hash, mainpkt);
+ hashKey(hash, subkeypkt);
+ if (pgpVerifySignatureRaw(digp, sigdigp, hash) == RPMRC_OK)
+ rc = 0;
+exit:
+ if (hash)
+ rpmDigestFinal(hash, NULL, NULL, 0);
+ pgpDigParamsFree(sigdigp);
+ 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;
+ struct pgpPkt mainpkt, pkt;
int rc = -1; /* assume failure */
while (p < pend) {
@@ -1087,6 +1137,7 @@ int pgpPrtParams(const uint8_t * pkts, s
} else {
digp = xcalloc(1, sizeof(*digp));
digp->tag = pkt.tag;
+ mainpkt = pkt;
}
}
@@ -1096,6 +1147,17 @@ int pgpPrtParams(const uint8_t * pkts, s
p += (pkt.body - pkt.head) + pkt.blen;
if (pkttype == PGPTAG_SIGNATURE)
break;
+ if (pkt.tag == PGPTAG_PUBLIC_SUBKEY) {
+ /* make sure that a binding signature follows and verify it */
+ struct pgpPkt sigpkt;
+ if (p == pend || decodePkt(p, (pend - p), &sigpkt)) {
+ digp = pgpDigParamsFree(digp);
+ break;
+ }
+ if (verifySubkeyBindingSignature(digp, &mainpkt, &pkt, &sigpkt))
+ break;
+ p += (sigpkt.body - sigpkt.head) + sigpkt.blen;
+ }
}
rc = (digp && (p == pend)) ? 0 : -1;
@@ -1137,7 +1199,7 @@ int pgpPrtParamsSubkeys(const uint8_t *p
digps[count] = xcalloc(1, sizeof(**digps));
digps[count]->tag = PGPTAG_PUBLIC_SUBKEY;
/* Copy UID from main key to subkey */
- digps[count]->userid = xstrdup(mainkey->userid);
+ digps[count]->userid = mainkey->userid ? xstrdup(mainkey->userid) : NULL;
if (getKeyID(pkt.body, pkt.blen, digps[count]->signid)) {
pgpDigParamsFree(digps[count]);
@@ -1148,6 +1210,17 @@ int pgpPrtParamsSubkeys(const uint8_t *p
pgpDigParamsFree(digps[count]);
continue;
}
+ /* check key flags from following binding signature */
+ if (p == pend || decodePkt(p, (pend - p), &pkt) || pkt.tag != PGPTAG_SIGNATURE || pgpPrtPkt(&pkt, digps[count])) {
+ pgpDigParamsFree(digps[count]);
+ continue;
+ }
+ if (!(digps[count]->key_flags & 0x02)) {
+ /* not a signing subkey */
+ pgpDigParamsFree(digps[count]);
+ continue;
+ }
+
count++;
}
}
@@ -1208,7 +1281,7 @@ char *pgpIdentItem(pgpDigParams digp)
return id;
}
-rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
+static rpmRC pgpVerifySignatureRaw(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
{
DIGEST_CTX ctx = rpmDigestDup(hashctx);
uint8_t *hash = NULL;
@@ -1260,6 +1333,13 @@ exit:
}
+rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
+{
+ if (!sig || sig->tag != PGPTAG_SIGNATURE || (sig->sigtype != PGPSIGTYPE_BINARY && sig->sigtype != PGPSIGTYPE_TEXT && sig->sigtype != PGPSIGTYPE_STANDALONE))
+ return RPMRC_FAIL;
+ return pgpVerifySignatureRaw(key, sig, hashctx);
+}
+
rpmRC pgpVerifySig(pgpDig dig, DIGEST_CTX hashctx)
{
if (dig == NULL || hashctx == NULL)