diff options
author | Werner Koch <[email protected]> | 2015-04-05 10:48:14 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2015-04-05 10:49:26 +0000 |
commit | d901efcebaefaf6eae4a9b9aa8f0c2c055d3518a (patch) | |
tree | 4d03e345d92a6354f549cfd5ec334642e96e08cf | |
parent | g10: Fix keytocard. (diff) | |
download | gnupg-d901efcebaefaf6eae4a9b9aa8f0c2c055d3518a.tar.gz gnupg-d901efcebaefaf6eae4a9b9aa8f0c2c055d3518a.zip |
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 <[email protected]>
-rw-r--r-- | g10/parse-packet.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/g10/parse-packet.c b/g10/parse-packet.c index d6a6d109f..c80b7df7d 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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) |