File pgpharden.diff of Package rpm
--- rpmio/rpmpgp.c.orig 2014-02-05 13:04:02.000000000 +0000
+++ rpmio/rpmpgp.c 2022-09-08 14:51:32.540386570 +0000
@@ -284,6 +284,7 @@ int pgpValTok(pgpValTbl vs, const char *
/** \ingroup rpmpgp
* Decode length from 1, 2, or 5 octet body length encoding, used in
* new format packet headers and V4 signature subpackets.
+ * Partial body lengths are (intentionally) not supported.
* @param s pointer to length encoding buffer
* @param slen buffer size
* @retval *lenp decoded length
@@ -303,14 +304,17 @@ size_t pgpLen(const uint8_t *s, size_t s
if (*s < 192) {
lenlen = 1;
dlen = *s;
- } else if (*s < 255 && slen > 2) {
+ } else if (*s < 224 && slen > 2) {
lenlen = 2;
dlen = (((s[0]) - 192) << 8) + s[1] + 192;
- } else if (slen > 5) {
+ } else if (*s == 255 && slen > 5) {
lenlen = 5;
dlen = pgpGrab(s+1, 4);
}
+ if (slen - lenlen < dlen)
+ lenlen = 0;
+
if (lenlen)
*lenp = dlen;
@@ -388,9 +392,11 @@ static int pgpPrtSubType(const uint8_t *
pgpDigParams _digp)
{
const uint8_t *p = h;
- size_t plen, i;
+ size_t plen = 0, i;
+ int rc = 0;
- while (hlen > 0) {
+ while (hlen > 0 && rc == 0) {
+ int impl = 0;
i = pgpLen(p, hlen, &plen);
if (i == 0 || i + plen > hlen)
break;
@@ -402,7 +408,7 @@ static int pgpPrtSubType(const uint8_t *
if (p[0] & PGPSUBTYPE_CRITICAL)
if (_print)
fprintf(stderr, " *CRITICAL*");
- switch (*p) {
+ switch (*p & ~PGPSUBTYPE_CRITICAL) {
case PGPSUBTYPE_PREFER_SYMKEY: /* preferred symmetric algorithms */
for (i = 1; i < plen; i++)
pgpPrtVal(" ", pgpSymkeyTbl, p[i]);
@@ -420,6 +426,7 @@ static int pgpPrtSubType(const uint8_t *
pgpPrtVal(" ", pgpKeyServerPrefsTbl, p[i]);
break;
case PGPSUBTYPE_SIG_CREATE_TIME:
+ impl = *p;
if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
{
@@ -437,6 +444,7 @@ static int pgpPrtSubType(const uint8_t *
break;
case PGPSUBTYPE_ISSUER_KEYID: /* issuer key ID */
+ impl = *p;
if (!(_digp->saved & PGPDIG_SAVED_ID) &&
(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
{
@@ -474,10 +482,18 @@ static int pgpPrtSubType(const uint8_t *
break;
}
pgpPrtNL();
+
+ if (!impl && (p[0] & PGPSUBTYPE_CRITICAL))
+ rc = 1;
+
p += plen;
hlen -= plen;
}
- return (hlen != 0); /* non-zero hlen is an error */
+
+ if (hlen != 0)
+ rc = 1;
+
+ return rc;
}
pgpDigAlg pgpDigAlgFree(pgpDigAlg alg)
@@ -499,9 +515,9 @@ static int pgpPrtSigParams(pgpTag tag, u
int i;
pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo);
- for (i = 0; i < sigalg->mpis && p + 2 <= pend; i++) {
+ for (i = 0; i < sigalg->mpis && pend - p >= 2; i++) {
int mpil = pgpMpiLen(p);
- if (p + mpil > pend)
+ if (pend - p < mpil)
break;
if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
if (sigalg->setmpi(sigalg, i, p))
@@ -523,12 +539,29 @@ static int pgpPrtSigParams(pgpTag tag, u
return rc;
}
+static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send,
+ unsigned int *valp)
+{
+ int rc = -1;
+
+ *valp = 0;
+ if (nbytes <= 4 && send - s >= nbytes) {
+ unsigned int val = pgpGrab(s, nbytes);
+ if (send - s - nbytes >= val) {
+ rc = 0;
+ *valp = val;
+ }
+ }
+
+ return rc;
+}
+
static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
pgpDigParams _digp)
{
uint8_t version = h[0];
- uint8_t * p;
- size_t plen;
+ const uint8_t * p;
+ unsigned int plen;
int rc;
switch (version) {
@@ -570,6 +603,7 @@ static int pgpPrtSig(pgpTag tag, const u
} break;
case 4:
{ pgpPktSigV4 v = (pgpPktSigV4)h;
+ const uint8_t *const hend = h + hlen;
if (hlen <= sizeof(*v))
return 1;
@@ -581,10 +615,11 @@ static int pgpPrtSig(pgpTag tag, const u
pgpPrtNL();
p = &v->hashlen[0];
- plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
+ if (pgpGet(v->hashlen, sizeof(v->hashlen), hend, &plen))
+ return 1;
p += sizeof(v->hashlen);
- if ((p + plen) > (h + hlen))
+ if ((p + plen) > hend)
return 1;
if (_digp->pubkey_algo == 0) {
@@ -595,17 +630,19 @@ static int pgpPrtSig(pgpTag tag, const u
return 1;
p += plen;
- plen = pgpGrab(p,2);
+ if (pgpGet(p, 2, hend, &plen))
+ return 1;
p += 2;
- if ((p + plen) > (h + hlen))
+ if ((p + plen) > hend)
return 1;
if (pgpPrtSubType(p, plen, v->sigtype, _digp))
return 1;
p += plen;
- plen = pgpGrab(p,2);
+ if (h + hlen - p < 2)
+ return 1;
pgpPrtHex(" signhash16", p, 2);
pgpPrtNL();
@@ -618,7 +655,7 @@ static int pgpPrtSig(pgpTag tag, const u
}
p += 2;
- if (p > (h + hlen))
+ if (p > hend)
return 1;
rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
@@ -971,6 +1008,8 @@ int pgpPrtParams(const uint8_t * pkts, s
break;
p += (pkt.body - pkt.head) + pkt.blen;
+ if (pkttype == PGPTAG_SIGNATURE)
+ break;
}
rc = (digp && (p == pend)) ? 0 : -1;