projects
/
openssl.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Check for potentially exploitable overflows in asn1_d2i_read_bio
[openssl.git]
/
crypto
/
asn1
/
a_d2i_fp.c
diff --git
a/crypto/asn1/a_d2i_fp.c
b/crypto/asn1/a_d2i_fp.c
index ece40bc4c0033ba075178c8548d2c56ccf2819eb..52b2ebdb631b9941123eb605cdc6564ed32c8739 100644
(file)
--- a/
crypto/asn1/a_d2i_fp.c
+++ b/
crypto/asn1/a_d2i_fp.c
@@
-57,6
+57,7
@@
*/
#include <stdio.h>
*/
#include <stdio.h>
+#include <limits.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1_mac.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1_mac.h>
@@
-143,17
+144,11
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
BUF_MEM *b;
unsigned char *p;
int i;
BUF_MEM *b;
unsigned char *p;
int i;
- int ret=-1;
ASN1_const_CTX c;
ASN1_const_CTX c;
-
in
t want=HEADER_SIZE;
+
size_
t want=HEADER_SIZE;
int eos=0;
int eos=0;
-#if defined(__GNUC__) && defined(__ia64)
- /* pathetic compiler bug in all known versions as of Nov. 2002 */
- long off=0;
-#else
- int off=0;
-#endif
- int len=0;
+ size_t off=0;
+ size_t len=0;
b=BUF_MEM_new();
if (b == NULL)
b=BUF_MEM_new();
if (b == NULL)
@@
-169,7
+164,7
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
want-=(len-off);
{
want-=(len-off);
- if (!BUF_MEM_grow_clean(b,len+want))
+ if (
len + want < len ||
!BUF_MEM_grow_clean(b,len+want))
{
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
goto err;
{
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
goto err;
@@
-181,7
+176,14
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
goto err;
}
if (i > 0)
goto err;
}
if (i > 0)
+ {
+ if (len+i < len)
+ {
+ ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
+ goto err;
+ }
len+=i;
len+=i;
+ }
}
/* else data already loaded */
}
/* else data already loaded */
@@
-206,6
+208,11
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
/* no data body so go round again */
eos++;
{
/* no data body so go round again */
eos++;
+ if (eos < 0)
+ {
+ ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_HEADER_TOO_LONG);
+ goto err;
+ }
want=HEADER_SIZE;
}
else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
want=HEADER_SIZE;
}
else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
@@
-220,10
+227,16
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
else
{
/* suck in c.slen bytes of data */
else
{
/* suck in c.slen bytes of data */
- want=
(int)
c.slen;
+ want=c.slen;
if (want > (len-off))
{
want-=(len-off);
if (want > (len-off))
{
want-=(len-off);
+ if (want > INT_MAX /* BIO_read takes an int length */ ||
+ len+want < len)
+ {
+ ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
+ goto err;
+ }
if (!BUF_MEM_grow_clean(b,len+want))
{
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
if (!BUF_MEM_grow_clean(b,len+want))
{
ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ERR_R_MALLOC_FAILURE);
@@
-238,11
+251,18
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
+ /* This can't overflow because
+ * |len+want| didn't overflow. */
len+=i;
len+=i;
- want
-=
i;
+ want
-=
i;
}
}
}
}
- off+=(int)c.slen;
+ if (off + c.slen < off)
+ {
+ ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
+ goto err;
+ }
+ off+=c.slen;
if (eos <= 0)
{
break;
if (eos <= 0)
{
break;
@@
-252,9
+272,15
@@
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
}
}
}
}
+ if (off > INT_MAX)
+ {
+ ASN1err(ASN1_F_ASN1_D2I_READ_BIO,ASN1_R_TOO_LONG);
+ goto err;
+ }
+
*pb = b;
return off;
err:
if (b != NULL) BUF_MEM_free(b);
*pb = b;
return off;
err:
if (b != NULL) BUF_MEM_free(b);
- return
(ret)
;
+ return
-1
;
}
}