summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViktor Dukhovni <openssl-users@dukhovni.org>2016-04-19 22:23:24 -0400
committerViktor Dukhovni <openssl-users@dukhovni.org>2016-04-23 00:44:50 -0400
commit2442382e11c022aaab4fdc6975bd15d5a75c4db2 (patch)
treed29644d7ef93e4d5e2007896dc29b4f71957337e
parentf32774087f7b3db1f789688368d16d917757421e (diff)
downloadopenssl-new-2442382e11c022aaab4fdc6975bd15d5a75c4db2.tar.gz
Fix buffer overrun in ASN1_parse().
Backport of commits: 79c7f74d6cefd5d32fa20e69195ad3de834ce065 bdcd660e33710079b495cf5cc6a1aaa5d2dcd317 from master. Reviewed-by: Matt Caswell <matt@openssl.org>
-rw-r--r--crypto/asn1/asn1_lib.c18
-rw-r--r--crypto/asn1/asn1_par.c17
2 files changed, 20 insertions, 15 deletions
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index 0b61fc9309..54b683c151 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -63,7 +63,7 @@
#include <openssl/asn1_mac.h>
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
- int max);
+ long max);
static void asn1_put_length(unsigned char **pp, int length);
const char ASN1_version[] = "ASN.1" OPENSSL_VERSION_PTEXT;
@@ -131,7 +131,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
}
*ptag = tag;
*pclass = xclass;
- if (!asn1_get_length(&p, &inf, plength, (int)max))
+ if (!asn1_get_length(&p, &inf, plength, max))
goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
@@ -159,14 +159,14 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
- int max)
+ long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
- unsigned int i;
+ unsigned long i;
if (max-- < 1)
- return (0);
+ return 0;
if (*p == 0x80) {
*inf = 1;
ret = 0;
@@ -175,15 +175,11 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
- if (i > sizeof(long))
+ if (i > sizeof(ret) || max < i)
return 0;
- if (max-- == 0)
- return (0);
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
- if (max-- == 0)
- return (0);
}
} else
ret = i;
@@ -192,7 +188,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
return 0;
*pp = p;
*rl = (long)ret;
- return (1);
+ return 1;
}
/*
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
index 0ca985a2be..e85e3398b6 100644
--- a/crypto/asn1/asn1_par.c
+++ b/crypto/asn1/asn1_par.c
@@ -173,6 +173,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
goto end;
if (j & V_ASN1_CONSTRUCTED) {
+ const unsigned char *sp;
+
ep = p + len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
@@ -182,6 +184,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
goto end;
}
if ((j == 0x21) && (len == 0)) {
+ sp = p;
for (;;) {
r = asn1_parse2(bp, &p, (long)(tot - p),
offset + (p - *pp), depth + 1,
@@ -190,19 +193,25 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
ret = 0;
goto end;
}
- if ((r == 2) || (p >= tot))
+ if ((r == 2) || (p >= tot)) {
+ len = p - sp;
break;
+ }
}
- } else
+ } else {
+ long tmp = len;
+
while (p < ep) {
- r = asn1_parse2(bp, &p, (long)len,
- offset + (p - *pp), depth + 1,
+ sp = p;
+ r = asn1_parse2(bp, &p, tmp, offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0) {
ret = 0;
goto end;
}
+ tmp -= p - sp;
}
+ }
} else if (xclass != 0) {
p += len;
if (BIO_write(bp, "\n", 1) <= 0)