aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2015-04-05 10:48:14 +0000
committerWerner Koch <[email protected]>2015-04-05 10:49:26 +0000
commitd901efcebaefaf6eae4a9b9aa8f0c2c055d3518a (patch)
tree4d03e345d92a6354f549cfd5ec334642e96e08cf
parentg10: Fix keytocard. (diff)
downloadgnupg-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.c26
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)