Update from HEAD.
authorDr. Stephen Henson <steve@openssl.org>
Sat, 30 Apr 2005 13:08:56 +0000 (13:08 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sat, 30 Apr 2005 13:08:56 +0000 (13:08 +0000)
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c
crypto/asn1/tasn_dec.c

index ceaeb4cbe39a741a598a589fdbb7393ee6c0d117..d75aa0dc03a7b0583186155a267ab1aa70798949 100644 (file)
@@ -962,6 +962,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                            182
 #define ASN1_F_ASN1_GENERALIZEDTIME_SET                         178
 #define ASN1_F_ASN1_GET_OBJECT                          114
 #define ASN1_F_ASN1_HEADER_NEW                          115
index 887a4295e7f103a87456dd75a922b50a9acd653b..cb39d35a9a880bcb300b1dfd98ffb8ca4d0ba6fd 100644 (file)
@@ -86,6 +86,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_GET_OBJECT),     "ASN1_get_object"},
 {ERR_FUNC(ASN1_F_ASN1_HEADER_NEW),     "ASN1_HEADER_new"},
index 2426cb6253a302cb3b7cf26edb165f68eadf9b14..86c901199b6a67a095ea3ef67a99e55de7baf8b9 100644 (file)
@@ -66,6 +66,7 @@
 #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,
@@ -644,7 +645,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inl
                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;
@@ -807,12 +808,66 @@ int asn1_ex_c2i(ASN1_VALUE **pval, unsigned char *cont, int len, int utype, char
        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)
@@ -822,11 +877,6 @@ static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, in
        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 */