diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2011-10-26 14:01:41 +0300 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2011-10-26 14:11:47 +0300 |
commit | c1141ec3f31ce20a071e9be064baa079119637f6 (patch) | |
tree | cc65d6f2f29bf023d793e102f3c3849f22232e50 /rpmio/rpmpgp.c | |
parent | 3487544e96dba38d0991e2293d7855efb4a1aa6c (diff) | |
download | rpm-c1141ec3f31ce20a071e9be064baa079119637f6.tar.gz rpm-c1141ec3f31ce20a071e9be064baa079119637f6.tar.bz2 rpm-c1141ec3f31ce20a071e9be064baa079119637f6.zip |
Verify MPI size is within packet boundary in pgpMpiItem()
- Malformed data can claim the MPI size to be "arbitrarily" large,
pass packet end pointer to pgpMpiItem() and validate we have enough
bytes in the packet to contain the MPI before copying.
Diffstat (limited to 'rpmio/rpmpgp.c')
-rw-r--r-- | rpmio/rpmpgp.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c index 5828dc8d7..4e72b3106 100644 --- a/rpmio/rpmpgp.c +++ b/rpmio/rpmpgp.c @@ -342,10 +342,14 @@ fprintf(stderr, "*** %s %s\n", pre, pgpHexStr(dest, nbytes)); /** * @return NULL on error */ -static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p) +static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, + const uint8_t *p, const uint8_t *pend) { size_t nbytes = pgpMpiLen(p)-2; + if (p + nbytes + 2 > pend) + return NULL; + if (item == NULL) { if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL) return item; @@ -626,7 +630,7 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, { switch (i) { case 0: /* m**d */ - _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p); + _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p, pend); if (_dig->sigdata == NULL) return 1; break; @@ -828,12 +832,13 @@ static const uint8_t * pgpPrtPubkeyParams(uint8_t pubkey_algo, pgpDig _dig) { size_t i; + const uint8_t *pend = h + hlen; /* XXX we can't handle more than one key in a packet, error out */ if (_dig && _dig->keydata) return NULL; - for (i = 0; p < &h[hlen]; i++, p += pgpMpiLen(p)) { + for (i = 0; p < pend; i++, p += pgpMpiLen(p)) { char * mpi; if (pubkey_algo == PGPPUBKEYALGO_RSA) { if (i >= 2) break; @@ -845,10 +850,12 @@ static const uint8_t * pgpPrtPubkeyParams(uint8_t pubkey_algo, } switch (i) { case 0: /* n */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.modulus, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.rsa.modulus, p, pend); break; case 1: /* e */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.publicExponent, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.rsa.publicExponent, p, pend); break; default: break; @@ -865,16 +872,20 @@ static const uint8_t * pgpPrtPubkeyParams(uint8_t pubkey_algo, } switch (i) { case 0: /* p */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.prime, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.dsa.params.prime, p, pend); break; case 1: /* q */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.subPrime, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.dsa.params.subPrime, p, pend); break; case 2: /* g */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.base, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.dsa.params.base, p, pend); break; case 3: /* y */ - pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.publicValue, p); + pgpMpiItem(_dig->keydata->arena, + &_dig->keydata->u.dsa.publicValue, p, pend); break; default: break; |