]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
updated libtasn1
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 25 May 2014 19:35:55 +0000 (21:35 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 29 May 2014 17:01:03 +0000 (19:01 +0200)
lib/minitasn1/coding.c
lib/minitasn1/decoding.c
lib/minitasn1/element.c
lib/minitasn1/gstr.h
lib/minitasn1/libtasn1.h
lib/minitasn1/parser_aux.c
lib/minitasn1/parser_aux.h

index e4eb060bc8466b88289c441c13c4654cd8d28a71..d6b7cf411435f0538110f4c4f914e9483d180570 100644 (file)
@@ -594,7 +594,7 @@ _asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter,
 {
   asn1_node p;
   int tag_len, is_tag_implicit;
-  unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1];
+  unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
   unsigned long tag_implicit = 0;
   unsigned char tag_der[MAX_TAG_LEN];
 
@@ -1012,7 +1012,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
                 char *ErrorDescription)
 {
   asn1_node node, p, p2;
-  unsigned char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1];
+  unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
   int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old;
   int err;
   unsigned char *der = ider;
index 16f202a2c4c3e328169911483f85ec1e7e445fdb..a9aecc254b1aee4a72da71c445d08c3468cd4982 100644 (file)
 #include <limits.h>
 #include <intprops.h>
 
+#ifdef DEBUG
+# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
+#else
+# define warn()
+#endif
+
+#define HAVE_TWO(x) (x>=2?1:0)
+
+#define DECR_LEN(l, s) do { \
+         l -= s; \
+         if (l < 0) { \
+           warn(); \
+           result = ASN1_DER_ERROR; \
+           goto cleanup; \
+         } \
+       } while (0)
+
 static int
-_asn1_get_indefinite_length_string (const unsigned char *der, int *len);
+_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len);
 
 static void
 _asn1_error_description_tag_error (asn1_node node, char *ErrorDescription)
@@ -206,8 +223,7 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len)
   ret = asn1_get_length_der (ber, ber_len, len);
   if (ret == -1)
     {                          /* indefinite length method */
-      ret = ber_len;
-      err = _asn1_get_indefinite_length_string (ber + 1, &ret);
+      err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret);
       if (err != ASN1_SUCCESS)
        return -3;
     }
@@ -233,12 +249,11 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
                    int *ret_len, unsigned char *str, int str_size,
                    int *str_len)
 {
-  int len_len;
+  int len_len = 0;
 
   if (der_len <= 0)
     return ASN1_GENERIC_ERROR;
 
-  /* if(str==NULL) return ASN1_SUCCESS; */
   *str_len = asn1_get_length_der (der, der_len, &len_len);
 
   if (*str_len < 0)
@@ -246,7 +261,10 @@ asn1_get_octet_der (const unsigned char *der, int der_len,
 
   *ret_len = *str_len + len_len;
   if (str_size >= *str_len)
-    memcpy (str, der + len_len, *str_len);
+    {
+      if (*str_len > 0 && str != NULL)
+        memcpy (str, der + len_len, *str_len);
+    }
   else
     {
       return ASN1_MEM_ERROR;
@@ -265,9 +283,11 @@ _asn1_get_time_der (const unsigned char *der, int der_len, int *ret_len,
 
   if (der_len <= 0 || str == NULL)
     return ASN1_DER_ERROR;
+
   str_len = asn1_get_length_der (der, der_len, &len_len);
-  if (str_len < 0 || str_size < str_len)
+  if (str_len <= 0 || str_size < str_len)
     return ASN1_DER_ERROR;
+
   memcpy (str, der + len_len, str_len);
   str[str_len] = 0;
   *ret_len = str_len + len_len;
@@ -281,7 +301,7 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
 {
   int len_len, len, k;
   int leading;
-  char temp[20];
+  char temp[LTOSTR_MAX_SIZE];
   unsigned long val, val1;
 
   *ret_len = 0;
@@ -293,7 +313,7 @@ _asn1_get_objectid_der (const unsigned char *der, int der_len, int *ret_len,
 
   len = asn1_get_length_der (der, der_len, &len_len);
 
-  if (len < 0 || len > der_len || len_len > der_len)
+  if (len <= 0 || len + len_len > der_len)
     return ASN1_DER_ERROR;
 
   val1 = der[len_len] / 40;
@@ -355,10 +375,11 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
                  int *ret_len, unsigned char *str, int str_size,
                  int *bit_len)
 {
-  int len_len, len_byte;
+  int len_len = 0, len_byte;
 
   if (der_len <= 0)
     return ASN1_GENERIC_ERROR;
+
   len_byte = asn1_get_length_der (der, der_len, &len_len) - 1;
   if (len_byte < 0)
     return ASN1_DER_ERROR;
@@ -366,8 +387,14 @@ asn1_get_bit_der (const unsigned char *der, int der_len,
   *ret_len = len_byte + len_len + 1;
   *bit_len = len_byte * 8 - der[len_len];
 
+  if (*bit_len < 0)
+    return ASN1_DER_ERROR;
+
   if (str_size >= len_byte)
-    memcpy (str, der + len_len + 1, len_byte);
+    {
+      if (len_byte > 0 && str)
+        memcpy (str, der + len_len + 1, len_byte);
+    }
   else
     {
       return ASN1_MEM_ERROR;
@@ -383,6 +410,7 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
 {
   asn1_node p;
   int counter, len2, len3, is_tag_implicit;
+  int result;
   unsigned long tag, tag_implicit = 0;
   unsigned char class, class2, class_implicit = 0;
 
@@ -410,23 +438,21 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
              if (p->type & CONST_EXPLICIT)
                {
                  if (asn1_get_tag_der
-                     (der + counter, der_len - counter, &class, &len2,
+                     (der + counter, der_len, &class, &len2,
                       &tag) != ASN1_SUCCESS)
                    return ASN1_DER_ERROR;
 
-                 if (counter + len2 > der_len)
-                   return ASN1_DER_ERROR;
+                  DECR_LEN(der_len, len2);
                  counter += len2;
 
                  len3 =
-                   asn1_get_length_ber (der + counter, der_len - counter,
+                   asn1_get_length_ber (der + counter, der_len,
                                         &len2);
                  if (len3 < 0)
                    return ASN1_DER_ERROR;
 
+                  DECR_LEN(der_len, len2);
                  counter += len2;
-                 if (counter > der_len)
-                   return ASN1_DER_ERROR;
 
                  if (!is_tag_implicit)
                    {
@@ -463,11 +489,11 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
   if (is_tag_implicit)
     {
       if (asn1_get_tag_der
-         (der + counter, der_len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
-      if (counter + len2 > der_len)
-       return ASN1_DER_ERROR;
+
+      DECR_LEN(der_len, len2);
 
       if ((class != class_implicit) || (tag != tag_implicit))
        {
@@ -486,18 +512,16 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
       unsigned type = type_field (node->type);
       if (type == ASN1_ETYPE_TAG)
        {
-         counter = 0;
-         *ret_len = counter;
+         *ret_len = 0;
          return ASN1_SUCCESS;
        }
 
       if (asn1_get_tag_der
-         (der + counter, der_len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
 
-      if (counter + len2 > der_len)
-       return ASN1_DER_ERROR;
+      DECR_LEN(der_len, len2);
 
       switch (type)
        {
@@ -550,6 +574,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len,
   counter += len2;
   *ret_len = counter;
   return ASN1_SUCCESS;
+
+cleanup:
+  return result;
 }
 
 static int
@@ -641,97 +668,108 @@ _asn1_extract_der_octet (asn1_node node, const unsigned char *der,
                         int der_len)
 {
   int len2, len3;
-  int counter2, counter_end;
+  int counter, counter_end;
+  int result;
 
   len2 = asn1_get_length_der (der, der_len, &len3);
   if (len2 < -1)
     return ASN1_DER_ERROR;
 
-  counter2 = len3 + 1;
+  counter = len3 + 1;
 
   if (len2 == -1)
     counter_end = der_len - 2;
   else
     counter_end = der_len;
 
-  while (counter2 < counter_end)
+  while (counter < counter_end)
     {
-      len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3);
+      len2 = asn1_get_length_der (der + counter, der_len, &len3);
 
       if (len2 < -1)
        return ASN1_DER_ERROR;
 
-      if (len2 > 0)
+      if (len2 >= 0)
        {
-         _asn1_append_value (node, der + counter2 + len3, len2);
+         DECR_LEN(der_len, len2+len3);
+         _asn1_append_value (node, der + counter + len3, len2);
        }
       else
        {                       /* indefinite */
-
-         len2 =
-           _asn1_extract_der_octet (node, der + counter2 + len3,
-                                    der_len - counter2 - len3);
-         if (len2 < 0)
-           return len2;
+         DECR_LEN(der_len, len3);
+         result =
+           _asn1_extract_der_octet (node, der + counter + len3,
+                                    der_len);
+         if (result != ASN1_SUCCESS)
+           return result;
+         len2 = 0;
        }
 
-      counter2 += len2 + len3 + 1;
+      DECR_LEN(der_len, 1);
+      counter += len2 + len3 + 1;
     }
 
   return ASN1_SUCCESS;
+
+cleanup:
+  return result;
 }
 
 static int
-_asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len)
+_asn1_get_octet_string (asn1_node node, const unsigned char *der, int der_len, int *len)
 {
   int len2, len3, counter, tot_len, indefinite;
+  int result;
 
   counter = 0;
 
   if (*(der - 1) & ASN1_CLASS_STRUCTURED)
     {
       tot_len = 0;
-      indefinite = asn1_get_length_der (der, *len, &len3);
+      indefinite = asn1_get_length_der (der, der_len, &len3);
       if (indefinite < -1)
        return ASN1_DER_ERROR;
 
       counter += len3;
+      DECR_LEN(der_len, len3);
+
       if (indefinite >= 0)
        indefinite += len3;
 
       while (1)
        {
-         if (counter > (*len))
-           return ASN1_DER_ERROR;
-
          if (indefinite == -1)
            {
-             if ((der[counter] == 0) && (der[counter + 1] == 0))
+             if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
                {
                  counter += 2;
+                 DECR_LEN(der_len, 2);
                  break;
                }
            }
          else if (counter >= indefinite)
            break;
 
+          DECR_LEN(der_len, 1);
          if (der[counter] != ASN1_TAG_OCTET_STRING)
            return ASN1_DER_ERROR;
 
          counter++;
 
-         len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
+         len2 = asn1_get_length_der (der + counter, der_len, &len3);
          if (len2 <= 0)
            return ASN1_DER_ERROR;
 
+          DECR_LEN(der_len, len3 + len2);
          counter += len3 + len2;
+
          tot_len += len2;
        }
 
       /* copy */
       if (node)
        {
-         unsigned char temp[DER_LEN];
+         unsigned char temp[ASN1_MAX_LENGTH_SIZE];
          int ret;
 
          len2 = sizeof (temp);
@@ -739,7 +777,7 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len)
          asn1_length_der (tot_len, temp, &len2);
          _asn1_set_value (node, temp, len2);
 
-         ret = _asn1_extract_der_octet (node, der, *len);
+         ret = _asn1_extract_der_octet (node, der, der_len);
          if (ret != ASN1_SUCCESS)
            return ret;
 
@@ -747,10 +785,11 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len)
     }
   else
     {                          /* NOT STRUCTURED */
-      len2 = asn1_get_length_der (der, *len, &len3);
+      len2 = asn1_get_length_der (der, der_len, &len3);
       if (len2 < 0)
        return ASN1_DER_ERROR;
 
+      DECR_LEN(der_len, len3+len2);
       counter = len3 + len2;
       if (node)
        _asn1_set_value (node, der, counter);
@@ -759,12 +798,16 @@ _asn1_get_octet_string (const unsigned char *der, asn1_node node, int *len)
   *len = counter;
   return ASN1_SUCCESS;
 
+cleanup:
+  return result;
 }
 
 static int
-_asn1_get_indefinite_length_string (const unsigned char *der, int *len)
+_asn1_get_indefinite_length_string (const unsigned char *der,
+                                   int der_len, int *len)
 {
   int len2, len3, counter, indefinite;
+  int result;
   unsigned long tag;
   unsigned char class;
 
@@ -772,12 +815,11 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len)
 
   while (1)
     {
-      if ((*len) < counter)
-       return ASN1_DER_ERROR;
-
-      if ((der[counter] == 0) && (der[counter + 1] == 0))
+      if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
        {
          counter += 2;
+         DECR_LEN(der_len, 2);
+
          indefinite--;
          if (indefinite <= 0)
            break;
@@ -786,29 +828,35 @@ _asn1_get_indefinite_length_string (const unsigned char *der, int *len)
        }
 
       if (asn1_get_tag_der
-         (der + counter, *len - counter, &class, &len2,
+         (der + counter, der_len, &class, &len2,
           &tag) != ASN1_SUCCESS)
        return ASN1_DER_ERROR;
-      if (counter + len2 > *len)
-       return ASN1_DER_ERROR;
+
+      DECR_LEN(der_len, len2);
       counter += len2;
-      len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
+
+      len2 = asn1_get_length_der (der + counter, der_len, &len3);
       if (len2 < -1)
        return ASN1_DER_ERROR;
+
       if (len2 == -1)
        {
          indefinite++;
          counter += 1;
+          DECR_LEN(der_len, 1);
        }
       else
        {
          counter += len2 + len3;
+          DECR_LEN(der_len, len2+len3);
        }
     }
 
   *len = counter;
   return ASN1_SUCCESS;
 
+cleanup:
+  return result;
 }
 
 static void delete_unneeded_choice_fields(asn1_node p)
@@ -822,11 +870,13 @@ static void delete_unneeded_choice_fields(asn1_node p)
     }
 }
 
+
+
 /**
  * asn1_der_decoding:
  * @element: pointer to an ASN1 structure.
  * @ider: vector that contains the DER encoding.
- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
  * @errorDescription: null-terminated string contains details when an
  *   error occurred.
  *
@@ -842,7 +892,7 @@ static void delete_unneeded_choice_fields(asn1_node p)
  *   name (*@ELEMENT deleted).
  **/
 int
-asn1_der_decoding (asn1_node * element, const void *ider, int len,
+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                   char *errorDescription)
 {
   asn1_node node, p, p2, p3;
@@ -864,6 +914,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
   if (node->type & CONST_OPTION)
     {
       result = ASN1_GENERIC_ERROR;
+      warn();
       goto cleanup;
     }
 
@@ -881,11 +932,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              len2 = _asn1_strtol (p2->value, NULL, 10);
              if (len2 == -1)
                {
-                 if (!der[counter] && !der[counter + 1])
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
                    {
                      p = p2;
                      move = UP;
                      counter += 2;
+                     DECR_LEN(ider_len, 2);
                      continue;
                    }
                }
@@ -898,6 +950,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              else if (counter > len2)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              p2 = p2->down;
@@ -907,7 +960,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                    {
                      ris =
                          extract_tag_der_recursive (p2, der + counter,
-                                                len - counter, &len2);
+                                                    ider_len, &len2);
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -920,6 +973,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              if (p2 == NULL)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
            }
@@ -950,12 +1004,10 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
            {
              while (p->down)
                {
-                 if (counter < len)
-                   ris =
+                 ris =
                      extract_tag_der_recursive (p->down, der + counter,
-                                            len - counter, &len2);
-                 else
-                   ris = ASN1_DER_ERROR;
+                                                ider_len, &len2);
+
                  if (ris == ASN1_SUCCESS)
                    {
                      delete_unneeded_choice_fields(p->down);
@@ -964,6 +1016,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                  else if (ris == ASN1_ERROR_TYPE_ANY)
                    {
                      result = ASN1_ERROR_TYPE_ANY;
+                      warn();
                      goto cleanup;
                    }
                  else
@@ -978,6 +1031,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                  if (!(p->type & CONST_OPTION))
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
                }
@@ -989,13 +1043,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
            {
              p2 = _asn1_find_up (p);
              len2 = _asn1_strtol (p2->value, NULL, 10);
+
              if ((len2 != -1) && (counter > len2))
                ris = ASN1_TAG_ERROR;
            }
 
          if (ris == ASN1_SUCCESS)
            ris =
-             extract_tag_der_recursive (p, der + counter, len - counter, &len2);
+             extract_tag_der_recursive (p, der + counter, ider_len, &len2);
+
          if (ris != ASN1_SUCCESS)
            {
              if (p->type & CONST_OPTION)
@@ -1014,11 +1070,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                    _asn1_error_description_tag_error (p, errorDescription);
 
                  result = ASN1_TAG_ERROR;
+                  warn();
                  goto cleanup;
                }
            }
          else
-           counter += len2;
+           {
+             DECR_LEN(ider_len, len2);
+             counter += len2;
+           }
        }
 
       if (ris == ASN1_SUCCESS)
@@ -1026,18 +1086,23 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
          switch (type_field (p->type))
            {
            case ASN1_ETYPE_NULL:
+             DECR_LEN(ider_len, 1);
              if (der[counter])
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              counter++;
              move = RIGHT;
              break;
            case ASN1_ETYPE_BOOLEAN:
+             DECR_LEN(ider_len, 2);
+
              if (der[counter++] != 1)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
              if (der[counter++] == 0)
@@ -1049,50 +1114,68 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
            case ASN1_ETYPE_INTEGER:
            case ASN1_ETYPE_ENUMERATED:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
+             DECR_LEN(ider_len, len3+len2);
+
              _asn1_set_value (p, der + counter, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OBJECT_ID:
              result =
-               _asn1_get_objectid_der (der + counter, len - counter, &len2,
+               _asn1_get_objectid_der (der + counter, ider_len, &len2,
                                        temp, sizeof (temp));
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
+
+             DECR_LEN(ider_len, len2);
 
              tlen = strlen (temp);
              if (tlen > 0)
                _asn1_set_value (p, temp, tlen + 1);
+
              counter += len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_GENERALIZED_TIME:
            case ASN1_ETYPE_UTC_TIME:
              result =
-               _asn1_get_time_der (der + counter, len - counter, &len2, temp,
+               _asn1_get_time_der (der + counter, ider_len, &len2, temp,
                                    sizeof (temp) - 1);
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
+
+             DECR_LEN(ider_len, len2);
 
              tlen = strlen (temp);
              if (tlen > 0)
                _asn1_set_value (p, temp, tlen);
+
              counter += len2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OCTET_STRING:
-             len3 = len - counter;
-             result = _asn1_get_octet_string (der + counter, p, &len3);
+             result = _asn1_get_octet_string (p, der + counter, ider_len, &len3);
              if (result != ASN1_SUCCESS)
-               goto cleanup;
+               {
+                  warn();
+                 goto cleanup;
+               }
 
+             DECR_LEN(ider_len, len3);
              counter += len3;
              move = RIGHT;
              break;
@@ -1107,13 +1190,16 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
            case ASN1_ETYPE_VISIBLE_STRING:
            case ASN1_ETYPE_BIT_STRING:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
+             DECR_LEN(ider_len, len3+len2);
+
              _asn1_set_value (p, der + counter, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
@@ -1126,18 +1212,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                  _asn1_set_value (p, NULL, 0);
                  if (len2 == -1)
                    {           /* indefinite length method */
-                     if (len - counter + 1 > 0)
-                       {
-                         if ((der[counter]) || der[counter + 1])
-                           {
-                             result = ASN1_DER_ERROR;
-                             goto cleanup;
-                           }
-                       }
-                     else
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
+                     DECR_LEN(ider_len, 2);
+                     if ((der[counter]) || der[counter + 1])
+                       {
+                         result = ASN1_DER_ERROR;
+                          warn();
+                         goto cleanup;
                        }
                      counter += 2;
                    }
@@ -1146,6 +1226,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1154,13 +1235,17 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              else
                {               /* move==DOWN || move==RIGHT */
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
+
+                 DECR_LEN(ider_len, len2);
                  counter += len2;
+
                  if (len3 > 0)
                    {
                      _asn1_ltostr (counter + len3, temp);
@@ -1199,13 +1284,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                  len2 = _asn1_strtol (p->value, NULL, 10);
                  if (len2 == -1)
                    {           /* indefinite length method */
-                     if ((counter + 2) > len)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-
-                     if ((der[counter]) || der[counter + 1])
+                     if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
                        {
                          _asn1_append_sequence_set (p);
                          p = p->down;
@@ -1214,7 +1293,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                          move = RIGHT;
                          continue;
                        }
+
                      _asn1_set_value (p, NULL, 0);
+                     DECR_LEN(ider_len, 2);
                      counter += 2;
                    }
                  else
@@ -1228,10 +1309,12 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                          move = RIGHT;
                          continue;
                        }
+
                      _asn1_set_value (p, NULL, 0);
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1239,12 +1322,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              else
                {               /* move==DOWN || move==RIGHT */
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
                    {
                      result = ASN1_DER_ERROR;
+                      warn();
                      goto cleanup;
                    }
+
+                 DECR_LEN(ider_len, len2);
                  counter += len2;
                  if (len3)
                    {
@@ -1273,46 +1359,59 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
              break;
            case ASN1_ETYPE_ANY:
              if (asn1_get_tag_der
-                 (der + counter, len - counter, &class, &len2,
+                 (der + counter, ider_len, &class, &len2,
                   &tag) != ASN1_SUCCESS)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
 
-             if (counter + len2 > len)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
+             DECR_LEN(ider_len, len2);
+
              len4 =
                asn1_get_length_der (der + counter + len2,
-                                    len - counter - len2, &len3);
+                                    ider_len, &len3);
              if (len4 < -1)
                {
                  result = ASN1_DER_ERROR;
+                  warn();
                  goto cleanup;
                }
-             if (len4 != -1)
+             if (len4 != -1) /* definite */
                {
                  len2 += len4;
+
+                 DECR_LEN(ider_len, len4+len3);
                  _asn1_set_value_lv (p, der + counter, len2 + len3);
                  counter += len2 + len3;
                }
-             else
+             else /* == -1 */
                {               /* indefinite length */
+                 ider_len += len2; /* undo DECR_LEN */
+
+                 if (counter == 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                      warn();
+                     goto cleanup;
+                   }
+
                  /* Check indefinite lenth method in an EXPLICIT TAG */
                  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
                    indefinite = 1;
                  else
                    indefinite = 0;
 
-                 len2 = len - counter;
                  result =
-                   _asn1_get_indefinite_length_string (der + counter, &len2);
+                   _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
                  if (result != ASN1_SUCCESS)
-                   goto cleanup;
+                   {
+                      warn();
+                     goto cleanup;
+                   }
 
+                 DECR_LEN(ider_len, len2);
                  _asn1_set_value_lv (p, der + counter, len2);
                  counter += len2;
 
@@ -1320,6 +1419,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                     an indefinite length method. */
                  if (indefinite)
                    {
+                     DECR_LEN(ider_len, 2);
                      if (!der[counter] && !der[counter + 1])
                        {
                          counter += 2;
@@ -1327,6 +1427,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
                      else
                        {
                          result = ASN1_DER_ERROR;
+                          warn();
                          goto cleanup;
                        }
                    }
@@ -1362,8 +1463,9 @@ asn1_der_decoding (asn1_node * element, const void *ider, int len,
 
   _asn1_delete_not_used (*element);
 
-  if (counter != len)
+  if (ider_len != 0)
     {
+      warn();
       result = ASN1_DER_ERROR;
       goto cleanup;
     }
@@ -1396,6 +1498,9 @@ cleanup:
  * decoding procedure, the *@STRUCTURE is deleted and set equal to
  * %NULL.
  *
+ * This function is deprecated and may just be an alias to asn1_der_decoding
+ * in future versions. Use asn1_der_decoding() instead.
+ *
  * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
  *   if ELEMENT is %NULL or @elementName == NULL, and
  *   %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't
@@ -1405,71 +1510,72 @@ int
 asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                           const void *ider, int len, char *errorDescription)
 {
-  asn1_node node, p, p2, p3, nodeFound = NULL;
-  char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p;
-  int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state;
-  int counter, len2, len3, len4, move, ris, tlen;
+  return asn1_der_decoding(structure, ider, len, errorDescription);
+}
+
+/**
+ * asn1_der_decoding_startEnd:
+ * @element: pointer to an ASN1 element
+ * @ider: vector that contains the DER encoding.
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+ * @name_element: an element of NAME structure.
+ * @start: the position of the first byte of NAME_ELEMENT decoding
+ *   (@ider[*start])
+ * @end: the position of the last byte of NAME_ELEMENT decoding
+ *  (@ider[*end])
+ *
+ * Find the start and end point of an element in a DER encoding
+ * string. I mean that if you have a der encoding and you have already
+ * used the function asn1_der_decoding() to fill a structure, it may
+ * happen that you want to find the piece of string concerning an
+ * element of the structure.
+ *
+ * One example is the sequence "tbsCertificate" inside an X509
+ * certificate.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if ELEMENT is %asn1_node EMPTY or @name_element is not a valid
+ *   element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
+ *   doesn't match the structure ELEMENT.
+ **/
+int
+asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len,
+                           const char *name_element, int *start, int *end)
+{
+  asn1_node node, node_to_find, p, p2;
+  int counter, len2, len3, len4, move, ris;
   unsigned char class;
   unsigned long tag;
-  int indefinite, result;
+  int indefinite, result = ASN1_DER_ERROR;
   const unsigned char *der = ider;
 
-  node = *structure;
+  node = element;
 
   if (node == NULL)
     return ASN1_ELEMENT_NOT_FOUND;
 
-  if (elementName == NULL)
-    {
-      result = ASN1_ELEMENT_NOT_FOUND;
-      goto cleanup;
-    }
+  node_to_find = asn1_find_node (node, name_element);
 
-  if (node->type & CONST_OPTION)
+  if (node_to_find == NULL)
+    return ASN1_ELEMENT_NOT_FOUND;
+
+  if (node_to_find == node)
     {
-      result = ASN1_GENERIC_ERROR;
-      goto cleanup;
+      *start = 0;
+      *end = ider_len - 1;
+      return ASN1_SUCCESS;
     }
 
-  if ((*structure)->name[0] != 0)
-    {                          /* Has *structure got a name? */
-      nameLen -= strlen ((*structure)->name);
-      if (nameLen > 0)
-       strcpy (currentName, (*structure)->name);
-      else
-       {
-         result = ASN1_MEM_ERROR;
-         goto cleanup;
-       }
-      if (!(strcmp (currentName, elementName)))
-       {
-         state = FOUND;
-         nodeFound = *structure;
-       }
-      else if (!memcmp (currentName, elementName, strlen (currentName)))
-       state = SAME_BRANCH;
-      else
-       state = OTHER_BRANCH;
-    }
-  else
-    {                          /* *structure doesn't have a name? */
-      currentName[0] = 0;
-      if (elementName[0] == 0)
-       {
-         state = FOUND;
-         nodeFound = *structure;
-       }
-      else
-       {
-         state = SAME_BRANCH;
-       }
-    }
+  if (node->type & CONST_OPTION)
+    return ASN1_GENERIC_ERROR;
 
   counter = 0;
   move = DOWN;
   p = node;
   while (1)
     {
+      if (p == NULL)
+       return ASN1_DER_ERROR;
 
       ris = ASN1_SUCCESS;
 
@@ -1478,26 +1584,45 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
          if (p->type & CONST_SET)
            {
              p2 = _asn1_find_up (p);
+             if (p2 == NULL)
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
+
              len2 = _asn1_strtol (p2->value, NULL, 10);
-             if (counter == len2)
+             if (len2 == -1)
+               {
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+                   {
+                     p = p2;
+                     move = UP;
+                     counter += 2;
+                     DECR_LEN(ider_len, 2);
+                     continue;
+                   }
+               }
+             else if (counter == len2)
                {
                  p = p2;
                  move = UP;
                  continue;
                }
              else if (counter > len2)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
                }
+
              p2 = p2->down;
+
              while (p2)
                {
                  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
-                   {
+                   {           /* CONTROLLARE */
                      ris =
                          extract_tag_der_recursive (p2, der + counter,
-                                                len - counter, &len2);
+                                                ider_len, &len2);
                      if (ris == ASN1_SUCCESS)
                        {
                          p2->type &= ~CONST_NOT_USED;
@@ -1508,84 +1633,34 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                  p2 = p2->right;
                }
              if (p2 == NULL)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
                }
            }
 
-         if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
-           {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
-             if (counter == len2)
-               {
-                 if (p->right)
-                   {
-                     p2 = p->right;
-                     move = RIGHT;
-                   }
-                 else
-                   move = UP;
-
-                 if (p->type & CONST_OPTION)
-                   asn1_delete_structure (&p);
-
-                 p = p2;
-                 continue;
-               }
-           }
+         if (p == node_to_find)
+           *start = counter;
 
          if (type_field (p->type) == ASN1_ETYPE_CHOICE)
            {
-             while (p->down)
-               {
-                 if (counter < len)
-                   ris =
-                     _asn1_extract_tag_der (p->down, der + counter,
-                                            len - counter, &len2);
-                 else
-                   ris = ASN1_DER_ERROR;
-                 if (ris == ASN1_SUCCESS)
-                   {
-                     delete_unneeded_choice_fields(p->down);
-                     break;
-                   }
-                 else if (ris == ASN1_ERROR_TYPE_ANY)
-                   {
-                     result = ASN1_ERROR_TYPE_ANY;
-                     goto cleanup;
-                   }
-                 else
-                   {
-                     p2 = p->down;
-                     asn1_delete_structure (&p2);
-                   }
-               }
-
-             if (p->down == NULL)
-               {
-                 if (!(p->type & CONST_OPTION))
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
+             p = p->down;
+             if (p == NULL)
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
                }
-             else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
-               p = p->down;
-           }
 
-         if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
-           {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
-             if (counter > len2)
-               ris = ASN1_TAG_ERROR;
+             ris =
+               _asn1_extract_tag_der (p, der + counter, ider_len,
+                                      &len2);
+             if (p == node_to_find)
+               *start = counter;
            }
 
          if (ris == ASN1_SUCCESS)
            ris =
-             _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
+             _asn1_extract_tag_der (p, der + counter, ider_len, &len2);
          if (ris != ASN1_SUCCESS)
            {
              if (p->type & CONST_OPTION)
@@ -1595,724 +1670,19 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
                }
              else if (p->type & CONST_DEFAULT)
                {
-                 _asn1_set_value (p, NULL, 0);
                  move = RIGHT;
                }
              else
                {
-                 if (errorDescription != NULL)
-                   _asn1_error_description_tag_error (p, errorDescription);
-
-                 result = ASN1_TAG_ERROR;
-                 goto cleanup;
+                 warn();
+                 return ASN1_TAG_ERROR;
                }
            }
          else
-           counter += len2;
-       }
-
-      if (ris == ASN1_SUCCESS)
-       {
-         switch (type_field (p->type))
-           {
-           case ASN1_ETYPE_NULL:
-             if (der[counter])
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (p == nodeFound)
-               state = EXIT;
-
-             counter++;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_BOOLEAN:
-             if (der[counter++] != 1)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (state == FOUND)
-               {
-                 if (der[counter++] == 0)
-                   _asn1_set_value (p, "F", 1);
-                 else
-                   _asn1_set_value (p, "T", 1);
-
-                 if (p == nodeFound)
-                   state = EXIT;
-
-               }
-             else
-               counter++;
-
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_INTEGER:
-           case ASN1_ETYPE_ENUMERATED:
-             len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
-             if (len2 < 0)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (state == FOUND)
-               {
-                 if (len3 + len2 > len - counter)
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
-                 _asn1_set_value (p, der + counter, len3 + len2);
-
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             counter += len3 + len2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_OBJECT_ID:
-             if (state == FOUND)
-               {
-                 result =
-                   _asn1_get_objectid_der (der + counter, len - counter,
-                                           &len2, temp, sizeof (temp));
-                 if (result != ASN1_SUCCESS)
-                   goto cleanup;
-
-                 tlen = strlen (temp);
-
-                 if (tlen > 0)
-                   _asn1_set_value (p, temp, tlen + 1);
-
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             else
-               {
-                 len2 =
-                   asn1_get_length_der (der + counter, len - counter, &len3);
-                 if (len2 < 0)
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
-                 len2 += len3;
-               }
-
-             counter += len2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_GENERALIZED_TIME:
-           case ASN1_ETYPE_UTC_TIME:
-             if (state == FOUND)
-               {
-                 result =
-                   _asn1_get_time_der (der + counter, len - counter, &len2,
-                                       temp, sizeof (temp) - 1);
-                 if (result != ASN1_SUCCESS)
-                   goto cleanup;
-
-                 tlen = strlen (temp);
-                 if (tlen > 0)
-                   _asn1_set_value (p, temp, tlen + 1);
-
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             else
-               {
-                 len2 =
-                   asn1_get_length_der (der + counter, len - counter, &len3);
-                 if (len2 < 0)
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
-                 len2 += len3;
-               }
-
-             counter += len2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_OCTET_STRING:
-             len3 = len - counter;
-             if (state == FOUND)
-               {
-                 result = _asn1_get_octet_string (der + counter, p, &len3);
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             else
-               result = _asn1_get_octet_string (der + counter, NULL, &len3);
-
-             if (result != ASN1_SUCCESS)
-               goto cleanup;
-
-             counter += len3;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_GENERALSTRING:
-           case ASN1_ETYPE_NUMERIC_STRING:
-           case ASN1_ETYPE_IA5_STRING:
-           case ASN1_ETYPE_TELETEX_STRING:
-           case ASN1_ETYPE_PRINTABLE_STRING:
-           case ASN1_ETYPE_UNIVERSAL_STRING:
-           case ASN1_ETYPE_BMP_STRING:
-           case ASN1_ETYPE_UTF8_STRING:
-           case ASN1_ETYPE_VISIBLE_STRING:
-           case ASN1_ETYPE_BIT_STRING:
-             len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
-             if (len2 < 0)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (state == FOUND)
-               {
-                 if (len3 + len2 > len - counter)
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
-                 _asn1_set_value (p, der + counter, len3 + len2);
-
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             counter += len3 + len2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_SEQUENCE:
-           case ASN1_ETYPE_SET:
-             if (move == UP)
-               {
-                 len2 = _asn1_strtol (p->value, NULL, 10);
-                 _asn1_set_value (p, NULL, 0);
-                 if (len2 == -1)
-                   {           /* indefinite length method */
-                     if ((der[counter]) || der[counter + 1])
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                     counter += 2;
-                   }
-                 else
-                   {           /* definite length method */
-                     if (len2 != counter)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                   }
-                 if (p == nodeFound)
-                   state = EXIT;
-                 move = RIGHT;
-               }
-             else
-               {               /* move==DOWN || move==RIGHT */
-                 if (state == OTHER_BRANCH)
-                   {
-                     len3 =
-                       asn1_get_length_der (der + counter, len - counter,
-                                            &len2);
-                     if (len3 < 0)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                     counter += len2 + len3;
-                     move = RIGHT;
-                   }
-                 else
-                   {           /*  state==SAME_BRANCH or state==FOUND */
-                     len3 =
-                       asn1_get_length_der (der + counter, len - counter,
-                                            &len2);
-                     if (len3 < 0)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                     counter += len2;
-                     if (len3 > 0)
-                       {
-                         _asn1_ltostr (counter + len3, temp);
-                         tlen = strlen (temp);
-
-                         if (tlen > 0)
-                           _asn1_set_value (p, temp, tlen + 1);
-                         move = DOWN;
-                       }
-                     else if (len3 == 0)
-                       {
-                         p2 = p->down;
-                         while (p2)
-                           {
-                             if (type_field (p2->type) != ASN1_ETYPE_TAG)
-                               {
-                                 p3 = p2->right;
-                                 asn1_delete_structure (&p2);
-                                 p2 = p3;
-                               }
-                             else
-                               p2 = p2->right;
-                           }
-                         move = RIGHT;
-                       }
-                     else
-                       {       /* indefinite length method */
-                         _asn1_set_value (p, "-1", 3);
-                         move = DOWN;
-                       }
-                   }
-               }
-             break;
-           case ASN1_ETYPE_SEQUENCE_OF:
-           case ASN1_ETYPE_SET_OF:
-             if (move == UP)
-               {
-                 len2 = _asn1_strtol (p->value, NULL, 10);
-                 if (len2 > counter)
-                   {
-                     _asn1_append_sequence_set (p);
-                     p = p->down;
-                     while (p->right)
-                       p = p->right;
-                     move = RIGHT;
-                     continue;
-                   }
-                 _asn1_set_value (p, NULL, 0);
-                 if (len2 != counter)
-                   {
-                     result = ASN1_DER_ERROR;
-                     goto cleanup;
-                   }
-
-                 if (p == nodeFound)
-                   state = EXIT;
-               }
-             else
-               {               /* move==DOWN || move==RIGHT */
-                 if (state == OTHER_BRANCH)
-                   {
-                     len3 =
-                       asn1_get_length_der (der + counter, len - counter,
-                                            &len2);
-                     if (len3 < 0)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                     counter += len2 + len3;
-                     move = RIGHT;
-                   }
-                 else
-                   {           /* state==FOUND or state==SAME_BRANCH */
-                     len3 =
-                       asn1_get_length_der (der + counter, len - counter,
-                                            &len2);
-                     if (len3 < 0)
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                     counter += len2;
-                     if (len3)
-                       {
-                         _asn1_ltostr (counter + len3, temp);
-                         tlen = strlen (temp);
-
-                         if (tlen > 0)
-                           _asn1_set_value (p, temp, tlen + 1);
-                         p2 = p->down;
-                         while ((type_field (p2->type) == ASN1_ETYPE_TAG)
-                                || (type_field (p2->type) ==
-                                    ASN1_ETYPE_SIZE))
-                           p2 = p2->right;
-                         if (p2->right == NULL)
-                           _asn1_append_sequence_set (p);
-                         p = p2;
-                         state = FOUND;
-                       }
-                   }
-               }
-
-             break;
-           case ASN1_ETYPE_ANY:
-             if (asn1_get_tag_der
-                 (der + counter, len - counter, &class, &len2,
-                  &tag) != ASN1_SUCCESS)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (counter + len2 > len)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             len4 =
-               asn1_get_length_der (der + counter + len2,
-                                    len - counter - len2, &len3);
-             if (len4 < -1)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-
-             if (len4 != -1)
-               {
-                 len2 += len4;
-                 if (state == FOUND)
-                   {
-                     _asn1_set_value_lv (p, der + counter, len2 + len3);
-
-                     if (p == nodeFound)
-                       state = EXIT;
-                   }
-                 counter += len2 + len3;
-               }
-             else
-               {               /* indefinite length */
-                 /* Check indefinite lenth method in an EXPLICIT TAG */
-                 if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
-                   indefinite = 1;
-                 else
-                   indefinite = 0;
-
-                 len2 = len - counter;
-                 result =
-                   _asn1_get_indefinite_length_string (der + counter, &len2);
-                 if (result != ASN1_SUCCESS)
-                   goto cleanup;
-
-                 if (state == FOUND)
-                   {
-                     _asn1_set_value_lv (p, der + counter, len2);
-
-                     if (p == nodeFound)
-                       state = EXIT;
-                   }
-
-                 counter += len2;
-
-                 /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
-                    an indefinite length method. */
-                 if (indefinite)
-                   {
-                     if (!der[counter] && !der[counter + 1])
-                       {
-                         counter += 2;
-                       }
-                     else
-                       {
-                         result = ASN1_DER_ERROR;
-                         goto cleanup;
-                       }
-                   }
-               }
-             move = RIGHT;
-             break;
-
-           default:
-             move = (move == UP) ? RIGHT : DOWN;
-             break;
-           }
-       }
-
-      if ((p == node && move != DOWN) || (state == EXIT))
-       break;
-
-      if (move == DOWN)
-       {
-         if (p->down)
-           {
-             p = p->down;
-
-             if (state != FOUND)
-               {
-                 nameLen -= strlen (p->name) + 1;
-                 if (nameLen > 0)
-                   {
-                     if (currentName[0])
-                       strcat (currentName, ".");
-                     strcat (currentName, p->name);
-                   }
-                 else
-                   {
-                     result = ASN1_MEM_ERROR;
-                     goto cleanup;
-                   }
-                 if (!(strcmp (currentName, elementName)))
-                   {
-                     state = FOUND;
-                     nodeFound = p;
-                   }
-                 else
-                   if (!memcmp
-                       (currentName, elementName, strlen (currentName)))
-                   state = SAME_BRANCH;
-                 else
-                   state = OTHER_BRANCH;
-               }
-           }
-         else
-           move = RIGHT;
-       }
-
-      if ((move == RIGHT) && !(p->type & CONST_SET))
-       {
-         if (p->right)
-           {
-             p = p->right;
-
-             if (state != FOUND)
-               {
-                 dot_p = char_p = currentName;
-                 while ((char_p = strchr (char_p, '.')))
-                   {
-                     dot_p = char_p++;
-                     dot_p++;
-                   }
-
-                 nameLen += strlen (currentName) - (dot_p - currentName);
-                 *dot_p = 0;
-
-                 nameLen -= strlen (p->name);
-                 if (nameLen > 0)
-                   strcat (currentName, p->name);
-                 else
-                   {
-                     result = ASN1_MEM_ERROR;
-                     goto cleanup;
-                   }
-
-                 if (!(strcmp (currentName, elementName)))
-                   {
-                     state = FOUND;
-                     nodeFound = p;
-                   }
-                 else
-                   if (!memcmp
-                       (currentName, elementName, strlen (currentName)))
-                   state = SAME_BRANCH;
-                 else
-                   state = OTHER_BRANCH;
-               }
-           }
-         else
-           move = UP;
-       }
-
-      if (move == UP)
-       {
-         p = _asn1_find_up (p);
-
-         if (state != FOUND)
-           {
-             dot_p = char_p = currentName;
-             while ((char_p = strchr (char_p, '.')))
-               {
-                 dot_p = char_p++;
-                 dot_p++;
-               }
-
-             nameLen += strlen (currentName) - (dot_p - currentName);
-             *dot_p = 0;
-
-             if (!(strcmp (currentName, elementName)))
-               {
-                 state = FOUND;
-                 nodeFound = p;
-               }
-             else
-               if (!memcmp (currentName, elementName, strlen (currentName)))
-               state = SAME_BRANCH;
-             else
-               state = OTHER_BRANCH;
-           }
-       }
-    }
-
-  _asn1_delete_not_used (*structure);
-
-  if (counter > len)
-    {
-      result = ASN1_DER_ERROR;
-      goto cleanup;
-    }
-
-  return ASN1_SUCCESS;
-
-cleanup:
-  asn1_delete_structure (structure);
-  return result;
-}
-
-/**
- * asn1_der_decoding_startEnd:
- * @element: pointer to an ASN1 element
- * @ider: vector that contains the DER encoding.
- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]
- * @name_element: an element of NAME structure.
- * @start: the position of the first byte of NAME_ELEMENT decoding
- *   (@ider[*start])
- * @end: the position of the last byte of NAME_ELEMENT decoding
- *  (@ider[*end])
- *
- * Find the start and end point of an element in a DER encoding
- * string. I mean that if you have a der encoding and you have already
- * used the function asn1_der_decoding() to fill a structure, it may
- * happen that you want to find the piece of string concerning an
- * element of the structure.
- *
- * One example is the sequence "tbsCertificate" inside an X509
- * certificate.
- *
- * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
- *   if ELEMENT is %asn1_node EMPTY or @name_element is not a valid
- *   element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
- *   doesn't match the structure ELEMENT.
- **/
-int
-asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
-                           const char *name_element, int *start, int *end)
-{
-  asn1_node node, node_to_find, p, p2;
-  int counter, len2, len3, len4, move, ris;
-  unsigned char class;
-  unsigned long tag;
-  int indefinite;
-  const unsigned char *der = ider;
-
-  node = element;
-
-  if (node == NULL)
-    return ASN1_ELEMENT_NOT_FOUND;
-
-  node_to_find = asn1_find_node (node, name_element);
-
-  if (node_to_find == NULL)
-    return ASN1_ELEMENT_NOT_FOUND;
-
-  if (node_to_find == node)
-    {
-      *start = 0;
-      *end = len - 1;
-      return ASN1_SUCCESS;
-    }
-
-  if (node->type & CONST_OPTION)
-    return ASN1_GENERIC_ERROR;
-
-  counter = 0;
-  move = DOWN;
-  p = node;
-  while (1)
-    {
-      if (p == NULL)
-       return ASN1_DER_ERROR;
-
-      ris = ASN1_SUCCESS;
-
-      if (move != UP)
-       {
-         if (p->type & CONST_SET)
-           {
-             p2 = _asn1_find_up (p);
-             if (p2 == NULL)
-               return ASN1_DER_ERROR;
-
-             len2 = _asn1_strtol (p2->value, NULL, 10);
-             if (len2 == -1)
-               {
-                 if (!der[counter] && !der[counter + 1])
-                   {
-                     p = p2;
-                     move = UP;
-                     counter += 2;
-                     continue;
-                   }
-               }
-             else if (counter == len2)
-               {
-                 p = p2;
-                 move = UP;
-                 continue;
-               }
-             else if (counter > len2)
-               return ASN1_DER_ERROR;
-
-             p2 = p2->down;
-
-             while (p2)
-               {
-                 if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
-                   {           /* CONTROLLARE */
-                     ris =
-                         extract_tag_der_recursive (p2, der + counter,
-                                                len - counter, &len2);
-                     if (ris == ASN1_SUCCESS)
-                       {
-                         p2->type &= ~CONST_NOT_USED;
-                         p = p2;
-                         break;
-                       }
-                   }
-                 p2 = p2->right;
-               }
-             if (p2 == NULL)
-               return ASN1_DER_ERROR;
-           }
-
-         if (p == node_to_find)
-           *start = counter;
-
-         if (type_field (p->type) == ASN1_ETYPE_CHOICE)
-           {
-             p = p->down;
-             if (p == NULL)
-               return ASN1_DER_ERROR;
-
-             ris =
-               _asn1_extract_tag_der (p, der + counter, len - counter,
-                                      &len2);
-             if (p == node_to_find)
-               *start = counter;
-           }
-
-         if (ris == ASN1_SUCCESS)
-           ris =
-             _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
-         if (ris != ASN1_SUCCESS)
            {
-             if (p->type & CONST_OPTION)
-               {
-                 p->type |= CONST_NOT_USED;
-                 move = RIGHT;
-               }
-             else if (p->type & CONST_DEFAULT)
-               {
-                 move = RIGHT;
-               }
-             else
-               {
-                 return ASN1_TAG_ERROR;
-               }
+             DECR_LEN(ider_len, len2);
+             counter += len2;
            }
-         else
-           counter += len2;
        }
 
       if (ris == ASN1_SUCCESS)
@@ -2320,22 +1690,36 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
          switch (type_field (p->type))
            {
            case ASN1_ETYPE_NULL:
+              DECR_LEN(ider_len, 1);
+
              if (der[counter])
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
              counter++;
              move = RIGHT;
              break;
            case ASN1_ETYPE_BOOLEAN:
-             if (der[counter++] != 1)
-               return ASN1_DER_ERROR;
-             counter++;
+              DECR_LEN(ider_len, 2);
+
+             if (der[counter] != 1)
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
+
+             counter += 2;
              move = RIGHT;
              break;
            case ASN1_ETYPE_OCTET_STRING:
-             len3 = len - counter;
-             ris = _asn1_get_octet_string (der + counter, NULL, &len3);
+             ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3);
              if (ris != ASN1_SUCCESS)
-               return ris;
+               {
+                 warn();
+                 return ris;
+               }
+              DECR_LEN(ider_len, len3);
              counter += len3;
              move = RIGHT;
              break;
@@ -2355,9 +1739,14 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
            case ASN1_ETYPE_VISIBLE_STRING:
            case ASN1_ETYPE_BIT_STRING:
              len2 =
-               asn1_get_length_der (der + counter, len - counter, &len3);
+               asn1_get_length_der (der + counter, ider_len, &len3);
              if (len2 < 0)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
+
+              DECR_LEN(ider_len, len3 + len2);
              counter += len3 + len2;
              move = RIGHT;
              break;
@@ -2366,10 +1755,16 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
              if (move != UP)
                {
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
-                   return ASN1_DER_ERROR;
+                   {
+                     warn();
+                     return ASN1_DER_ERROR;
+                   }
+
+                  DECR_LEN(ider_len, len2);
                  counter += len2;
+
                  if (len3 == 0)
                    move = RIGHT;
                  else
@@ -2377,8 +1772,11 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
                }
              else
                {
-                 if (!der[counter] && !der[counter + 1])       /* indefinite length method */
-                   counter += 2;
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
+                   {
+                     counter += 2;
+                     DECR_LEN(ider_len, 2);
+                   }
                  move = RIGHT;
                }
              break;
@@ -2387,13 +1785,26 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
              if (move != UP)
                {
                  len3 =
-                   asn1_get_length_der (der + counter, len - counter, &len2);
+                   asn1_get_length_der (der + counter, ider_len, &len2);
                  if (len3 < -1)
-                   return ASN1_DER_ERROR;
+                   {
+                     warn();
+                     return ASN1_DER_ERROR;
+                   }
+
+                  DECR_LEN(ider_len, len2);
                  counter += len2;
-                 if ((len3 == -1) && !der[counter] && !der[counter + 1])
-                   counter += 2;
-                 else if (len3)
+
+                 if (len3 == -1)
+                   {
+                      if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+                        {
+                          DECR_LEN(ider_len, 2);
+                          counter += 2;
+                        }
+                   }
+
+                 if (len3)
                    {
                      p2 = p->down;
                      while ((type_field (p2->type) == ASN1_ETYPE_TAG) ||
@@ -2404,52 +1815,79 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
                }
              else
                {
-                 if (!der[counter] && !der[counter + 1])       /* indefinite length method */
-                   counter += 2;
+                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
+                   {
+                     DECR_LEN(ider_len, 2);
+                     counter += 2;
+                   }
                }
              move = RIGHT;
              break;
            case ASN1_ETYPE_ANY:
              if (asn1_get_tag_der
-                 (der + counter, len - counter, &class, &len2,
+                 (der + counter, ider_len, &class, &len2,
                   &tag) != ASN1_SUCCESS)
-               return ASN1_DER_ERROR;
-             if (counter + len2 > len)
-               return ASN1_DER_ERROR;
+                {
+                   warn();
+                   return ASN1_DER_ERROR;
+                }
+
+             DECR_LEN(ider_len, len2);
 
              len4 =
                asn1_get_length_der (der + counter + len2,
-                                    len - counter - len2, &len3);
+                                    ider_len, &len3);
              if (len4 < -1)
-               return ASN1_DER_ERROR;
+               {
+                 warn();
+                 return ASN1_DER_ERROR;
+               }
 
              if (len4 != -1)
                {
-                 counter += len2 + len4 + len3;
+                 DECR_LEN(ider_len, len3 + len4);
+                 counter += len2 + len3 + len4;
                }
              else
                {               /* indefinite length */
                  /* Check indefinite lenth method in an EXPLICIT TAG */
+                 ider_len += len2; /* undo DECR_LEN */
+
+                 if (counter == 0)
+                   {
+                     result = ASN1_DER_ERROR;
+                      warn();
+                     goto cleanup;
+                   }
+
                  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
                    indefinite = 1;
                  else
                    indefinite = 0;
 
-                 len2 = len - counter;
                  ris =
-                   _asn1_get_indefinite_length_string (der + counter, &len2);
+                   _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
                  if (ris != ASN1_SUCCESS)
-                   return ris;
+                   {
+                     warn();
+                     return ris;
+                   }
                  counter += len2;
+                 DECR_LEN(ider_len, len2);
 
                  /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
                     an indefinite length method. */
                  if (indefinite)
                    {
+                     DECR_LEN(ider_len, 2);
+
                      if (!der[counter] && !der[counter + 1])
                        counter += 2;
                      else
-                       return ASN1_DER_ERROR;
+                       {
+                         warn();
+                         return ASN1_DER_ERROR;
+                       }
                    }
                }
              move = RIGHT;
@@ -2487,7 +1925,11 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int len,
        p = _asn1_find_up (p);
     }
 
+  warn();
   return ASN1_ELEMENT_NOT_FOUND;
+
+cleanup:
+  return result;
 }
 
 /**
index 1fd988a88d15698309b4d35841262b39622a9ab7..ac30e46610160fdbaef92c7920e7ce8ba6125e49 100644 (file)
@@ -112,8 +112,11 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
     /* VALUE_OUT is too short to contain the value conversion */
     return ASN1_MEM_ERROR;
 
-  for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
-    value_out[k2 - k] = val[k2];
+  if (value_out != NULL)
+    {
+      for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+        value_out[k2 - k] = val[k2];
+    }
 
 #if 0
   printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
@@ -130,7 +133,7 @@ int
 _asn1_append_sequence_set (asn1_node node)
 {
   asn1_node p, p2;
-  char temp[10];
+  char temp[LTOSTR_MAX_SIZE];
   long n;
 
   if (!node || !(node->down))
@@ -621,7 +624,7 @@ asn1_write_value (asn1_node node_root, const char *name,
        if (ptr_size < data_size) { \
                return ASN1_MEM_ERROR; \
        } else { \
-               if (ptr) \
+               if (ptr && data_size > 0) \
                  memcpy (ptr, data, data_size); \
        }
 
@@ -631,8 +634,9 @@ asn1_write_value (asn1_node node_root, const char *name,
                return ASN1_MEM_ERROR; \
        } else { \
                /* this strcpy is checked */ \
-               if (ptr) \
+               if (ptr) \
                  _asn1_strcpy (ptr, data); \
+               } \
        }
 
 #define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
@@ -642,37 +646,41 @@ asn1_write_value (asn1_node node_root, const char *name,
        } else { \
                /* this strcpy is checked */ \
                if (ptr) { \
-                 memcpy (ptr, data, data_size); \
+                 if (data_size > 0) \
+                   memcpy (ptr, data, data_size); \
                  ptr[data_size] = 0; \
                } \
        }
 
 #define ADD_STR_VALUE( ptr, ptr_size, data) \
-       *len = (int) _asn1_strlen (data) + 1; \
-       if (ptr_size < (int) _asn1_strlen (ptr) + (*len)) { \
-               return ASN1_MEM_ERROR; \
-       } else { \
-               /* this strcat is checked */ \
-               if (ptr) _asn1_strcat (ptr, data); \
-       }
+        *len += _asn1_strlen(data); \
+        if (ptr_size < (int) *len) { \
+                (*len)++; \
+                return ASN1_MEM_ERROR; \
+        } else { \
+                /* this strcat is checked */ \
+                if (ptr) _asn1_strcat (ptr, data); \
+        }
 
 /**
  * asn1_read_value:
  * @root: pointer to a structure.
  * @name: the name of the element inside a structure that you want to read.
  * @ivalue: vector that will contain the element's content, must be a
- *   pointer to memory cells already allocated.
+ *   pointer to memory cells already allocated (may be %NULL).
  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
  *   holds the sizeof value.
  *
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure. 
+ * If an element is OPTIONAL and this returns
  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
  * in the der encoding that created the structure.  The first element
  * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
  * so on.
  *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
  * INTEGER: VALUE will contain a two's complement form integer.
  *
  *            integer=-1  -> value[0]=0xFF , len=1.
@@ -728,19 +736,22 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
  * @root: pointer to a structure.
  * @name: the name of the element inside a structure that you want to read.
  * @ivalue: vector that will contain the element's content, must be a
- *   pointer to memory cells already allocated.
+ *   pointer to memory cells already allocated (may be %NULL).
  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
  *   holds the sizeof value.
  * @etype: The type of the value read (ASN1_ETYPE)
  *
- * Returns the value of one element inside a structure.
- *
- * If an element is OPTIONAL and the function "read_value" returns
+ * Returns the value of one element inside a structure. 
+ * If an element is OPTIONAL and this returns
  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
  * in the der encoding that created the structure.  The first element
  * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
  * so on.
  *
+ * Note that there can be valid values with length zero. In these case
+ * this function will succeed and @len will be zero.
+ *
+ *
  * INTEGER: VALUE will contain a two's complement form integer.
  *
  *            integer=-1  -> value[0]=0xFF , len=1.
@@ -790,7 +801,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
                      int *len, unsigned int *etype)
 {
   asn1_node node, p, p2;
-  int len2, len3;
+  int len2, len3, result;
   int value_size = *len;
   unsigned char *value = ivalue;
   unsigned type;
@@ -848,9 +859,10 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
          if ((isdigit (p->value[0])) || (p->value[0] == '-')
              || (p->value[0] == '+'))
            {
-             if (_asn1_convert_integer
-                 (p->value, value, value_size, len) != ASN1_SUCCESS)
-               return ASN1_MEM_ERROR;
+             result = _asn1_convert_integer
+                 (p->value, value, value_size, len);
+              if (result != ASN1_SUCCESS)
+               return result;
            }
          else
            {                   /* is an identifier like v1 */
@@ -861,10 +873,11 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
                    {
                      if (!_asn1_strcmp (p2->name, p->value))
                        {
-                         if (_asn1_convert_integer
+                         result = _asn1_convert_integer
                              (p2->value, value, value_size,
-                              len) != ASN1_SUCCESS)
-                           return ASN1_MEM_ERROR;
+                              len);
+                         if (result != ASN1_SUCCESS)
+                           return result;
                          break;
                        }
                    }
@@ -875,16 +888,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
       else
        {
          len2 = -1;
-         if (asn1_get_octet_der
+         result = asn1_get_octet_der
              (node->value, node->value_len, &len2, value, value_size,
-              len) != ASN1_SUCCESS)
-           return ASN1_MEM_ERROR;
+              len);
+          if (result != ASN1_SUCCESS)
+           return result;
        }
       break;
     case ASN1_ETYPE_OBJECT_ID:
       if (node->type & CONST_ASSIGN)
        {
-         value[0] = 0;
+         *len = 0;
+         if (value)
+               value[0] = 0;
          p = node->down;
          while (p)
            {
@@ -898,7 +914,7 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
                }
              p = p->right;
            }
-         *len = _asn1_strlen (value) + 1;
+         (*len)++;
        }
       else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
        {
@@ -927,17 +943,19 @@ asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
     case ASN1_ETYPE_UTF8_STRING:
     case ASN1_ETYPE_VISIBLE_STRING:
       len2 = -1;
-      if (asn1_get_octet_der
+      result = asn1_get_octet_der
          (node->value, node->value_len, &len2, value, value_size,
-          len) != ASN1_SUCCESS)
-       return ASN1_MEM_ERROR;
+          len);
+      if (result != ASN1_SUCCESS)
+       return result;
       break;
     case ASN1_ETYPE_BIT_STRING:
       len2 = -1;
-      if (asn1_get_bit_der
+      result = asn1_get_bit_der
          (node->value, node->value_len, &len2, value, value_size,
-          len) != ASN1_SUCCESS)
-       return ASN1_MEM_ERROR;
+          len);
+      if (result != ASN1_SUCCESS)
+       return result;
       break;
     case ASN1_ETYPE_CHOICE:
       PUT_STR_VALUE (value, value_size, node->down->name);
index 51db059489ccb5e31f7dab4232cb29f7f34231de..00c335ca93eddffd46988988e524abc6389e98d9 100644 (file)
@@ -25,3 +25,18 @@ void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
 
 #define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
 #define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
+
+inline static
+void safe_memset(void *data, int c, size_t size)
+{
+       volatile unsigned volatile_zero = 0;
+       volatile char *vdata = (volatile char*)data;
+
+       /* This is based on a nice trick for safe memset,
+        * sent by David Jacobson in the openssl-dev mailing list.
+        */
+
+       if (size > 0) do {
+               memset(data, c, size);
+       } while(vdata[volatile_zero] != c);
+}
index 92ae54eb4e55a1bea0e59b972dbb606948bb1988..a4570682e0b54eb9c0ad38903f719e267ec1d445 100644 (file)
@@ -44,7 +44,18 @@ extern "C"
 {
 #endif
 
-#define ASN1_VERSION "3.5"
+#define ASN1_VERSION "3.6"
+
+#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
+# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+# if _ASN1_GCC_VERSION >= 30100
+#  define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
+# endif
+#endif
+
+#ifndef _ASN1_GCC_ATTR_DEPRECATED
+#define _ASN1_GCC_ATTR_DEPRECATED
+#endif
 
   /*****************************************/
   /* Errors returned by libtasn1 functions */
@@ -251,11 +262,12 @@ extern "C"
     asn1_der_decoding (asn1_node * element, const void *ider,
                       int len, char *errorDescription);
 
+  /* Do not use. Use asn1_der_decoding() instead. */
   extern ASN1_API int
     asn1_der_decoding_element (asn1_node * structure,
                               const char *elementName,
                               const void *ider, int len,
-                              char *errorDescription);
+                              char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED;
 
   extern ASN1_API int
     asn1_der_decoding_startEnd (asn1_node element,
index b5f665db4c27d1d659cc5d3def7bcba91cf5a5bb..effedb23661a9bc4c5d90677f9915ddd2d2b0636 100644 (file)
@@ -458,11 +458,16 @@ _asn1_remove_node (asn1_node node, unsigned int flags)
   if (node == NULL)
     return;
 
-  if (flags & ASN1_DELETE_FLAG_ZEROIZE)
-    memset(node->value, 0, node->value_len);
+  if (node->value != NULL)
+    {
+      if (flags & ASN1_DELETE_FLAG_ZEROIZE)
+        {
+          safe_memset(node->value, 0, node->value_len);
+        }
 
-  if (node->value != NULL && node->value != node->small_value)
-    free (node->value);
+      if (node->value != node->small_value)
+        free (node->value);
+    }
   free (node);
 }
 
@@ -531,7 +536,7 @@ char *
 _asn1_ltostr (long v, char *str)
 {
   long d, r;
-  char temp[20];
+  char temp[LTOSTR_MAX_SIZE];
   int count, k, start;
 
   if (v < 0)
index bf378527fe5b6f7ec80585d690a15d9a4fe0669c..1f1aec26375b929d1b125be0195525292f389340 100644 (file)
@@ -22,8 +22,6 @@
 #ifndef _PARSER_AUX_H
 #define _PARSER_AUX_H
 
-#define DER_LEN 16
-
 /***************************************/
 /*  Functions used by ASN.1 parser     */
 /***************************************/
@@ -54,6 +52,7 @@ void _asn1_delete_list (void);
 
 void _asn1_delete_list_and_nodes (void);
 
+#define LTOSTR_MAX_SIZE 20
 char *_asn1_ltostr (long v, char *str);
 
 asn1_node _asn1_find_up (asn1_node node);