Add intelligence to asn1_d2i_read_bio for reading entire header without blocking for extra data
Reviewed-by: Tomas Mraz <tomas@openssl.foundation> Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> (Merged from https://github.com/openssl/openssl/pull/30401)
This commit is contained in:
parent
674c23d265
commit
35852da1d9
2 changed files with 50 additions and 4 deletions
|
|
@ -104,7 +104,7 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
#define HEADER_SIZE 2
|
||||
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
|
||||
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
|||
}
|
||||
i = BIO_read(in, &(b->data[len]), (int)want);
|
||||
|
||||
if (i <= 0 && diff == 0) {
|
||||
if (i <= 0) {
|
||||
ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -157,11 +157,57 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
|||
}
|
||||
/* else data already loaded */
|
||||
|
||||
/* make sure there is enough data for a complete header */
|
||||
p = (unsigned char *)&(b->data[off]);
|
||||
q = p;
|
||||
diff = len - off;
|
||||
if (diff == 0)
|
||||
if (diff < 2) {
|
||||
/* Failed sanity check */
|
||||
ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
|
||||
goto err;
|
||||
}
|
||||
|
||||
diff--;
|
||||
if ((*(q++) & V_ASN1_PRIMITIVE_TAG) == V_ASN1_PRIMITIVE_TAG) {
|
||||
/* Multi-byte tag. See if we have the whole thing yet */
|
||||
do {
|
||||
diff--;
|
||||
} while (diff > 0 && *(q++) & 0x80);
|
||||
|
||||
if (diff == 0) {
|
||||
/*
|
||||
* End of current data, will need at least 1 more byte for
|
||||
* length. 2 if the tag is still incomplete
|
||||
*/
|
||||
want = q - p + 2;
|
||||
if (*q & 0x80) {
|
||||
want++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the length. This should also work for indefinite length */
|
||||
diff--;
|
||||
if (*q & 0x80) {
|
||||
unsigned int i = *q & 0x7f;
|
||||
|
||||
if (i > sizeof(long)) {
|
||||
ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
if (i > diff) {
|
||||
want = q - p + i + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a complete header now, assuming we didn't hit EOF. Parse the
|
||||
* tag and length
|
||||
*/
|
||||
q = p;
|
||||
diff = len - off;
|
||||
inf = ASN1_get_object(&q, &slen, &tag, &xclass, (int)diff);
|
||||
if (inf & 0x80) {
|
||||
unsigned long e;
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
|||
*inf = 0;
|
||||
i = *p & 0x7f;
|
||||
if (*p++ & 0x80) {
|
||||
if (max < i + 1)
|
||||
if (max < i)
|
||||
return 0;
|
||||
/* Skip leading zeroes */
|
||||
while (i > 0 && *p == 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue