diff options
author | Ben Laurie <ben@links.org> | 2016-03-29 19:37:57 +0100 |
---|---|---|
committer | Ben Laurie <ben@links.org> | 2016-03-30 20:28:44 +0100 |
commit | 79c7f74d6cefd5d32fa20e69195ad3de834ce065 (patch) | |
tree | 843eaf62c96f9adfcbbd633fac1f7f863b362539 | |
parent | 087ca80ad83071dde0bb6bc1c28c743caa00eaf8 (diff) |
Fix buffer overrun in ASN1_parse().
Fix buffer overrun in asn1_get_length().
Reproducer: asn1parse-reproduce crash-6bfd417f47bc940f6984f5e639b637fd4e6074bc
Fix length calculations.
Reproducer: asn1parse-reproduce crash-1819d0e54cd2b0430626c59053e6077ef04c2ffb
Reproducer: asn1parse-reproduce crash-9969db8603e644ddc0ba3459b51eac7a2c4b729b
Make i long.
Reviewed-by: Rich Salz <rsalz@openssl.org>
-rw-r--r-- | crypto/asn1/asn1_lib.c | 14 | ||||
-rw-r--r-- | crypto/asn1/asn1_par.c | 17 |
2 files changed, 20 insertions, 11 deletions
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index da1ac78e06..938984d509 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -61,7 +61,7 @@ #include <openssl/asn1.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); static int _asn1_check_infinite_end(const unsigned char **p, long len) @@ -128,7 +128,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)) @@ -150,14 +150,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; @@ -166,7 +166,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, *inf = 0; i = *p & 0x7f; if (*(p++) & 0x80) { - if (max < (int)i) + if (max < (long)i + 1) return 0; /* Skip leading zeroes */ while (i && *p == 0) { @@ -186,7 +186,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 773b8b2ee3..b721273cf1 100644 --- a/crypto/asn1/asn1_par.c +++ b/crypto/asn1/asn1_par.c @@ -164,6 +164,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 = p; + ep = p + len; if (BIO_write(bp, "\n", 1) <= 0) goto end; @@ -181,19 +183,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 { while (p < ep) { - r = asn1_parse2(bp, &p, (long)len, + sp = p; + r = asn1_parse2(bp, &p, len, offset + (p - *pp), depth + 1, indent, dump); if (r == 0) { ret = 0; goto end; } + len -= p - sp; } + len = length; + } } else if (xclass != 0) { p += len; if (BIO_write(bp, "\n", 1) <= 0) @@ -229,7 +237,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, goto end; dump_cont = 1; } - BIO_printf(bp, ":%u", p[0]); + if (len > 0) + BIO_printf(bp, ":%u", p[0]); } else if (tag == V_ASN1_BMPSTRING) { /* do the BMP thang */ } else if (tag == V_ASN1_OCTET_STRING) { |