Limit recursion depth in old d2i_ASN1_bytes function
Thanks to Shi Lei for reporting this bug.
Reviewed-by: Rich Salz <rsalz@openssl.org>
(cherry picked from commit 81f69e5b69
)
This commit is contained in:
parent
6592de7c8c
commit
a199e0c39a
1 changed files with 43 additions and 15 deletions
|
@ -60,7 +60,12 @@
|
||||||
#include "cryptlib.h"
|
#include "cryptlib.h"
|
||||||
#include <openssl/asn1.h>
|
#include <openssl/asn1.h>
|
||||||
|
|
||||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
|
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
|
||||||
|
int depth);
|
||||||
|
static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
|
||||||
|
const unsigned char **pp, long length,
|
||||||
|
int Ptag, int Pclass, int depth,
|
||||||
|
int *perr);
|
||||||
/*
|
/*
|
||||||
* type is a 'bitmap' of acceptable string types.
|
* type is a 'bitmap' of acceptable string types.
|
||||||
*/
|
*/
|
||||||
|
@ -99,7 +104,7 @@ ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
ret = (*a);
|
ret = (*a);
|
||||||
|
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
s = OPENSSL_malloc((int)len + 1);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
i = ERR_R_MALLOC_FAILURE;
|
i = ERR_R_MALLOC_FAILURE;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -154,15 +159,38 @@ int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maximum recursion depth of d2i_ASN1_bytes(): much more than should be
|
||||||
|
* encountered in pratice.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ASN1_BYTES_MAXDEPTH 20
|
||||||
|
|
||||||
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
long length, int Ptag, int Pclass)
|
long length, int Ptag, int Pclass)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err);
|
||||||
|
if (err != 0)
|
||||||
|
ASN1err(ASN1_F_D2I_ASN1_BYTES, err);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
|
||||||
|
const unsigned char **pp, long length,
|
||||||
|
int Ptag, int Pclass,
|
||||||
|
int depth, int *perr)
|
||||||
{
|
{
|
||||||
ASN1_STRING *ret = NULL;
|
ASN1_STRING *ret = NULL;
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
unsigned char *s;
|
unsigned char *s;
|
||||||
long len;
|
long len;
|
||||||
int inf, tag, xclass;
|
int inf, tag, xclass;
|
||||||
int i = 0;
|
|
||||||
|
if (depth > ASN1_BYTES_MAXDEPTH) {
|
||||||
|
*perr = ASN1_R_NESTED_ASN1_STRING;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((a == NULL) || ((*a) == NULL)) {
|
if ((a == NULL) || ((*a) == NULL)) {
|
||||||
if ((ret = ASN1_STRING_new()) == NULL)
|
if ((ret = ASN1_STRING_new()) == NULL)
|
||||||
|
@ -173,18 +201,19 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
p = *pp;
|
p = *pp;
|
||||||
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
|
||||||
if (inf & 0x80) {
|
if (inf & 0x80) {
|
||||||
i = ASN1_R_BAD_OBJECT_HEADER;
|
*perr = ASN1_R_BAD_OBJECT_HEADER;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag != Ptag) {
|
if (tag != Ptag) {
|
||||||
i = ASN1_R_WRONG_TAG;
|
*perr = ASN1_R_WRONG_TAG;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inf & V_ASN1_CONSTRUCTED) {
|
if (inf & V_ASN1_CONSTRUCTED) {
|
||||||
ASN1_const_CTX c;
|
ASN1_const_CTX c;
|
||||||
|
|
||||||
|
c.error = 0;
|
||||||
c.pp = pp;
|
c.pp = pp;
|
||||||
c.p = p;
|
c.p = p;
|
||||||
c.inf = inf;
|
c.inf = inf;
|
||||||
|
@ -192,17 +221,18 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
c.tag = Ptag;
|
c.tag = Ptag;
|
||||||
c.xclass = Pclass;
|
c.xclass = Pclass;
|
||||||
c.max = (length == 0) ? 0 : (p + length);
|
c.max = (length == 0) ? 0 : (p + length);
|
||||||
if (!asn1_collate_primitive(ret, &c))
|
if (!asn1_collate_primitive(ret, &c, depth)) {
|
||||||
|
*perr = c.error;
|
||||||
goto err;
|
goto err;
|
||||||
else {
|
} else {
|
||||||
p = c.p;
|
p = c.p;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
if ((ret->length < len) || (ret->data == NULL)) {
|
if ((ret->length < len) || (ret->data == NULL)) {
|
||||||
s = (unsigned char *)OPENSSL_malloc((int)len + 1);
|
s = OPENSSL_malloc((int)len + 1);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
i = ERR_R_MALLOC_FAILURE;
|
*perr = ERR_R_MALLOC_FAILURE;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (ret->data != NULL)
|
if (ret->data != NULL)
|
||||||
|
@ -230,7 +260,6 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
err:
|
err:
|
||||||
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
|
||||||
ASN1_STRING_free(ret);
|
ASN1_STRING_free(ret);
|
||||||
ASN1err(ASN1_F_D2I_ASN1_BYTES, i);
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +271,8 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
|
||||||
* There have been a few bug fixes for this function from Paul Keogh
|
* There have been a few bug fixes for this function from Paul Keogh
|
||||||
* <paul.keogh@sse.ie>, many thanks to him
|
* <paul.keogh@sse.ie>, many thanks to him
|
||||||
*/
|
*/
|
||||||
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
|
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
|
||||||
|
int depth)
|
||||||
{
|
{
|
||||||
ASN1_STRING *os = NULL;
|
ASN1_STRING *os = NULL;
|
||||||
BUF_MEM b;
|
BUF_MEM b;
|
||||||
|
@ -270,9 +300,8 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
c->q = c->p;
|
c->q = c->p;
|
||||||
if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
|
if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass,
|
||||||
== NULL) {
|
depth + 1, &c->error) == NULL) {
|
||||||
c->error = ERR_R_ASN1_LIB;
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +326,6 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
|
||||||
ASN1_STRING_free(os);
|
ASN1_STRING_free(os);
|
||||||
return (1);
|
return (1);
|
||||||
err:
|
err:
|
||||||
ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE, c->error);
|
|
||||||
if (os != NULL)
|
if (os != NULL)
|
||||||
ASN1_STRING_free(os);
|
ASN1_STRING_free(os);
|
||||||
if (b.data != NULL)
|
if (b.data != NULL)
|
||||||
|
|
Loading…
Reference in a new issue