{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_GET_OBJECT), "ASN1_get_object"},
{ERR_FUNC(ASN1_F_ASN1_HEADER_NEW), "ASN1_HEADER_new"},
#include <openssl/err.h>
static int asn1_check_eoc(unsigned char **in, long len);
+static int asn1_find_end(unsigned char **in, long len, char inf);
static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag, int aclass);
static int collect_data(BUF_MEM *buf, unsigned char **p, long plen);
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst,
cont = *in;
/* If indefinite length constructed find the real end */
if(inf) {
- if(!asn1_collect(NULL, &p, plen, inf, -1, -1)) goto err;
+ if(!asn1_find_end(&p, plen, inf)) goto err;
len = p - cont;
} else {
len = p - cont + plen;
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(unsigned char **in, long len, char inf)
+ {
+ int expected_eoc;
+ long plen;
+ 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 justi
+ * 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, unsigned char **in, long len, char inf, int tag, int aclass)
char cst, ininf;
p = *in;
inf &= 1;
- /* If no buffer and not indefinite length constructed just pass over the encoded data */
- if(!buf && !inf) {
- *in += len;
- return 1;
- }
while(len > 0) {
q = p;
/* Check for EOC */