Use more efficient way to locate end of an ASN1 structure.
This commit is contained in:
parent
c1a8a5de13
commit
e1cc0671ac
3 changed files with 61 additions and 4 deletions
|
@ -1035,6 +1035,7 @@ void ERR_load_ASN1_strings(void);
|
|||
#define ASN1_F_ASN1_DUP 111
|
||||
#define ASN1_F_ASN1_ENUMERATED_SET 112
|
||||
#define ASN1_F_ASN1_ENUMERATED_TO_BN 113
|
||||
#define ASN1_F_ASN1_FIND_END 190
|
||||
#define ASN1_F_ASN1_GENERALIZEDTIME_SET 185
|
||||
#define ASN1_F_ASN1_GENERATE_V3 178
|
||||
#define ASN1_F_ASN1_GET_OBJECT 114
|
||||
|
|
|
@ -88,6 +88,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
|
|||
{ERR_FUNC(ASN1_F_ASN1_DUP), "ASN1_dup"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_SET), "ASN1_ENUMERATED_set"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_ENUMERATED_TO_BN), "ASN1_ENUMERATED_to_BN"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_FIND_END), "ASN1_FIND_END"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_GENERALIZEDTIME_SET), "ASN1_GENERALIZEDTIME_set"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_GENERATE_V3), "ASN1_generate_v3"},
|
||||
{ERR_FUNC(ASN1_F_ASN1_GET_OBJECT), "ASN1_get_object"},
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include <openssl/err.h>
|
||||
|
||||
static int asn1_check_eoc(const unsigned char **in, long len);
|
||||
static int asn1_find_end(const unsigned char **in, long len, char inf);
|
||||
|
||||
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
|
||||
char inf, int tag, int aclass);
|
||||
|
@ -848,7 +849,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
|
|||
/* If indefinite length constructed find the real end */
|
||||
if (inf)
|
||||
{
|
||||
if (!asn1_collect(NULL, &p, plen, inf, -1, -1))
|
||||
if (!asn1_find_end(&p, plen, inf))
|
||||
goto err;
|
||||
len = p - cont;
|
||||
}
|
||||
|
@ -1053,12 +1054,66 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* This function finds the end of an ASN1 structure when passed its maximum
|
||||
* length, whether it is indefinite length and a pointer to the content.
|
||||
* This is more efficient than calling asn1_collect because it does not
|
||||
* recurse on each indefinite length header.
|
||||
*/
|
||||
|
||||
static int asn1_find_end(const unsigned char **in, long len, char inf)
|
||||
{
|
||||
int expected_eoc;
|
||||
long plen;
|
||||
const unsigned char *p = *in, *q;
|
||||
/* If not indefinite length constructed just add length */
|
||||
if (inf == 0)
|
||||
{
|
||||
*in += len;
|
||||
return 1;
|
||||
}
|
||||
expected_eoc = 1;
|
||||
/* Indefinite length constructed form. Find the end when enough EOCs
|
||||
* are found. If more indefinite length constructed headers
|
||||
* are encountered increment the expected eoc count otherwise just
|
||||
* skip to the end of the data.
|
||||
*/
|
||||
while (len > 0)
|
||||
{
|
||||
if(asn1_check_eoc(&p, len))
|
||||
{
|
||||
expected_eoc--;
|
||||
if (expected_eoc == 0)
|
||||
break;
|
||||
len -= 2;
|
||||
continue;
|
||||
}
|
||||
q = p;
|
||||
/* Just read in a header: only care about the length */
|
||||
if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
|
||||
-1, 0, 0, NULL))
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (inf)
|
||||
expected_eoc++;
|
||||
else
|
||||
p += plen;
|
||||
len -= p - q;
|
||||
}
|
||||
if (expected_eoc)
|
||||
{
|
||||
ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC);
|
||||
return 0;
|
||||
}
|
||||
*in = p;
|
||||
return 1;
|
||||
}
|
||||
/* This function collects the asn1 data from a constructred string
|
||||
* type into a buffer. The values of 'in' and 'len' should refer
|
||||
* to the contents of the constructed type and 'inf' should be set
|
||||
* if it is indefinite length. If 'buf' is NULL then we just want
|
||||
* to find the end of the current structure: useful for indefinite
|
||||
* length constructed stuff.
|
||||
* if it is indefinite length.
|
||||
*/
|
||||
|
||||
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
|
||||
|
|
Loading…
Reference in a new issue