gpg: Fix DoS while parsing mangled secret key packets.

* g10/parse-packet.c (parse_key): Check PKTLEN before calling mpi_read
et al.
--

Due to the missing length checks PKTLEN may turn negative.  Because
PKTLEN is an unsigned int the malloc in read_rest would try to malloc
a too large number and terminate the process with "error reading rest
of packet: Cannot allocate memory".

Reported-by: Hanno Böck.
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-04-05 12:48:14 +02:00
parent f82c4a6d0d
commit d901efceba
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 25 additions and 1 deletions

View File

@ -2103,6 +2103,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
byte temp[16];
size_t snlen = 0;
if (pktlen < 1)
{
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
if (!pk->seckey_info)
{
@ -2303,6 +2309,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
}
else if (ski->is_protected)
{
if (pktlen < 2) /* At least two bytes for the length. */
{
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
/* Ugly: The length is encrypted too, so we read all stuff
* up to the end of the packet into the first SKEY
* element. */
@ -2323,7 +2335,14 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
/* Not encrypted. */
for (i = npkey; i < nskey; i++)
{
unsigned int n = pktlen;
unsigned int n;
if (pktlen < 2) /* At least two bytes for the length. */
{
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
n = pktlen;
pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
@ -2339,6 +2358,11 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
if (err)
goto leave;
if (pktlen < 2)
{
err = gpg_error (GPG_ERR_INV_PACKET);
goto leave;
}
ski->csum = read_16 (inp);
pktlen -= 2;
if (list_mode)