diff options
author | Demi Marie Obenour <demi@invisiblethingslab.com> | 2021-06-22 09:13:41 -0400 |
---|---|---|
committer | Florian Festi <ffesti@redhat.com> | 2022-01-25 09:38:32 +0100 |
commit | 714e606558b4517bd2d02d03a0ddad7da79a58c6 (patch) | |
tree | 82d54a1c7f57130797967183625b6e41b1319170 /rpmio/rpmpgp.c | |
parent | d5d743dcf3fa00909ddfb344bfe8469c3226b29a (diff) | |
download | rpm-714e606558b4517bd2d02d03a0ddad7da79a58c6.tar.gz |
Fix bounds checks in public key parsing
If a public key was too short for the curve ID, the code would
previously perform out-of-bounds pointer arithmetic, which is undefined
behavior in C. Check that the packet is long enough to contain the
curve ID before bumping `se` past the curve ID.
Furthermore, if a public key is too short to even contain the fixed-size
header, an out-of-bounds pointer would be created, which is also
undefined behavior. Fix this by returning early if the buffer is too
short.
Finally, return early if the public key algorithm or curve ID is
invalid, rather than relying in processMpis() to fail. While
processMpis() will error out, bailing out explicitly is much clearer.
Diffstat (limited to 'rpmio/rpmpgp.c')
-rw-r--r-- | rpmio/rpmpgp.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c index 35603286f..015c15a5c 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c @@ -834,28 +834,27 @@ int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen, { pgpPktKeyV4 v = (pgpPktKeyV4) (h); int mpis = -1; - /* Packet must be larger than v to have room for the required MPIs */ - if (hlen > sizeof(*v)) { - switch (v->pubkey_algo) { - case PGPPUBKEYALGO_RSA: - mpis = 2; - break; - case PGPPUBKEYALGO_DSA: - mpis = 4; - break; - case PGPPUBKEYALGO_EDDSA: - mpis = 1; - break; - } - } - + /* Packet must be strictly larger than v to have room for the + * required MPIs and (for EdDSA) the curve ID */ + if (hlen < sizeof(*v) + sizeof(uint8_t)) + return rc; se = (uint8_t *)(v + 1); - /* EdDSA has a curve id before the MPIs */ - if (v->pubkey_algo == PGPPUBKEYALGO_EDDSA) { - if (se < pend && se[0] != 0x00 && se[0] != 0xff) - se += 1 + se[0]; - else - se = pend; /* error out when reading the MPI */ + switch (v->pubkey_algo) { + case PGPPUBKEYALGO_EDDSA: + /* EdDSA has a curve id before the MPIs */ + if (se[0] == 0x00 || se[0] == 0xff || pend - se < 1 + se[0]) + return rc; + se += 1 + se[0]; + mpis = 1; + break; + case PGPPUBKEYALGO_RSA: + mpis = 2; + break; + case PGPPUBKEYALGO_DSA: + mpis = 4; + break; + default: + return rc; } /* Does the size and number of MPI's match our expectations? */ |