]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
minitasn1: updated to version 4.0
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 26 Jun 2014 12:25:40 +0000 (14:25 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 26 Jun 2014 12:25:40 +0000 (14:25 +0200)
lib/minitasn1/coding.c
lib/minitasn1/decoding.c
lib/minitasn1/element.c
lib/minitasn1/element.h
lib/minitasn1/int.h
lib/minitasn1/libtasn1.h
lib/minitasn1/parser_aux.c
lib/minitasn1/parser_aux.h
lib/minitasn1/structure.c

index d6b7cf411435f0538110f4c4f914e9483d180570..2dd80ba41953ca00127ba61b5d76e9d15b022d8f 100644 (file)
@@ -493,6 +493,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char *der,
                {
                  len2 = strtol (p->name, NULL, 10);
                  _asn1_set_name (p, NULL);
+
                  asn1_length_der (*counter - len2, temp, &len3);
                  if (len3 <= (*max_len))
                    {
@@ -1013,7 +1014,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
 {
   asn1_node node, p, p2;
   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 counter, counter_old, len2, len3, move, max_len, max_len_old;
   int err;
   unsigned char *der = ider;
 
@@ -1034,6 +1035,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
   counter = 0;
   move = DOWN;
   p = node;
+
   while (1)
     {
 
@@ -1041,6 +1043,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
       max_len_old = max_len;
       if (move != UP)
        {
+          p->start = counter;
          err = _asn1_insert_tag_der (p, der, &counter, &max_len);
          if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
            goto error;
@@ -1187,10 +1190,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
        case ASN1_ETYPE_SET:
          if (move != UP)
            {
-             _asn1_ltostr (counter, (char *) temp);
-             tlen = _asn1_strlen (temp);
-             if (tlen > 0)
-               _asn1_set_value (p, temp, tlen + 1);
+             p->tmp_ival = counter;
              if (p->down == NULL)
                {
                  move = UP;
@@ -1213,8 +1213,8 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
            }
          else
            {                   /* move==UP */
-             len2 = _asn1_strtol (p->value, NULL, 10);
-             _asn1_set_value (p, NULL, 0);
+             len2 = p->tmp_ival;
+             p->tmp_ival = 0;
              if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0))
                {
                  err = _asn1_ordering_set (der + len2, counter - len2, p);
@@ -1236,11 +1236,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
        case ASN1_ETYPE_SET_OF:
          if (move != UP)
            {
-             _asn1_ltostr (counter, (char *) temp);
-             tlen = _asn1_strlen (temp);
-
-             if (tlen > 0)
-               _asn1_set_value (p, temp, tlen + 1);
+             p->tmp_ival = counter;
              p = p->down;
              while ((type_field (p->type) == ASN1_ETYPE_TAG)
                     || (type_field (p->type) == ASN1_ETYPE_SIZE))
@@ -1252,13 +1248,13 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
                  continue;
                }
              else
-               p = _asn1_find_up (p);
+               p = _asn1_get_up (p);
              move = UP;
            }
          if (move == UP)
            {
-             len2 = _asn1_strtol (p->value, NULL, 10);
-             _asn1_set_value (p, NULL, 0);
+             len2 = p->tmp_ival;
+             p->tmp_ival = 0;
              if ((type_field (p->type) == ASN1_ETYPE_SET_OF)
                  && (counter - len2 > 0) && (max_len >= 0))
                {
@@ -1303,6 +1299,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
 
       if ((move != DOWN) && (counter != counter_old))
        {
+          p->end = counter - 1;
          err = _asn1_complete_explicit_tag (p, der, &counter, &max_len);
          if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
            goto error;
@@ -1326,7 +1323,7 @@ asn1_der_coding (asn1_node element, const char *name, void *ider, int *len,
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   *len = counter;
index a9aecc254b1aee4a72da71c445d08c3468cd4982..b7e49b4af30f1a5fcddae13336051daec91cfca9 100644 (file)
@@ -622,7 +622,7 @@ _asn1_delete_not_used (asn1_node node)
            {
              p2 = _asn1_find_left (p);
              if (!p2)
-               p2 = _asn1_find_up (p);
+               p2 = _asn1_get_up (p);
            }
          asn1_delete_structure (&p);
          p = p2;
@@ -645,7 +645,7 @@ _asn1_delete_not_used (asn1_node node)
            {
              while (1)
                {
-                 p = _asn1_find_up (p);
+                 p = _asn1_get_up (p);
                  if (p == node)
                    {
                      p = NULL;
@@ -871,20 +871,23 @@ static void delete_unneeded_choice_fields(asn1_node p)
 }
 
 
-
 /**
- * asn1_der_decoding:
+ * asn1_der_decoding2
  * @element: pointer to an ASN1 structure.
  * @ider: vector that contains the DER encoding.
- * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @max_ider_len: pointer to an integer giving the information about the
+ *   maximal number of bytes occupied by *@ider. The real size of the DER
+ *   encoding is returned through this pointer.
+ * @flags: flags controlling the behaviour of the function.
  * @errorDescription: null-terminated string contains details when an
  *   error occurred.
  *
- * Fill the structure *@ELEMENT with values of a DER encoding
- * string. The structure must just be created with function
- * asn1_create_element().  If an error occurs during the decoding
- * procedure, the *@ELEMENT is deleted and set equal to
- * %NULL.
+ * Fill the structure *@element with values of a DER encoding string. The
+ * structure must just be created with function asn1_create_element().
+ *
+ * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore
+ * padding after the decoded DER data. Upon a successful return the value of
+ * *@max_ider_len will be set to the number of bytes decoded.
  *
  * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
  *   if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
@@ -892,15 +895,16 @@ static void delete_unneeded_choice_fields(asn1_node p)
  *   name (*@ELEMENT deleted).
  **/
 int
-asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
-                  char *errorDescription)
+asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
+                   unsigned int flags, char *errorDescription)
 {
   asn1_node node, p, p2, p3;
   char temp[128];
   int counter, len2, len3, len4, move, ris, tlen;
+  asn1_node ptail = NULL;
   unsigned char class;
   unsigned long tag;
-  int indefinite, result;
+  int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len;
   const unsigned char *der = ider;
 
   node = *element;
@@ -928,8 +932,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
        {
          if (p->type & CONST_SET)
            {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
+             p2 = _asn1_get_up (p);
+             len2 = p2->tmp_ival;
              if (len2 == -1)
                {
                  if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
@@ -978,10 +982,14 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                }
            }
 
+         /* the position in the DER structure this starts */
+         p->start = counter;
+         p->end = total_len - 1;
+
          if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
            {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
+             p2 = _asn1_get_up (p);
+             len2 = p2->tmp_ival;
              if (counter == len2)
                {
                  if (p->right)
@@ -1037,12 +1045,14 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                }
              else if (type_field (p->type) != ASN1_ETYPE_CHOICE)
                p = p->down;
+
+             p->start = counter;
            }
 
          if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
            {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
+             p2 = _asn1_get_up (p);
+             len2 = p2->tmp_ival;
 
              if ((len2 != -1) && (counter > len2))
                ris = ASN1_TAG_ERROR;
@@ -1208,8 +1218,8 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
            case ASN1_ETYPE_SET:
              if (move == UP)
                {
-                 len2 = _asn1_strtol (p->value, NULL, 10);
-                 _asn1_set_value (p, NULL, 0);
+                 len2 = p->tmp_ival;
+                 p->tmp_ival = 0;
                  if (len2 == -1)
                    {           /* indefinite length method */
                      DECR_LEN(ider_len, 2);
@@ -1248,10 +1258,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
 
                  if (len3 > 0)
                    {
-                     _asn1_ltostr (counter + len3, temp);
-                     tlen = strlen (temp);
-                     if (tlen > 0)
-                       _asn1_set_value (p, temp, tlen + 1);
+                     p->tmp_ival = counter + len3;
                      move = DOWN;
                    }
                  else if (len3 == 0)
@@ -1272,7 +1279,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                    }
                  else
                    {           /* indefinite length method */
-                     _asn1_set_value (p, "-1", 3);
+                     p->tmp_ival = -1;
                      move = DOWN;
                    }
                }
@@ -1281,20 +1288,19 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
            case ASN1_ETYPE_SET_OF:
              if (move == UP)
                {
-                 len2 = _asn1_strtol (p->value, NULL, 10);
+                 len2 = p->tmp_ival;
                  if (len2 == -1)
                    {           /* indefinite length method */
                      if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
                        {
-                         _asn1_append_sequence_set (p);
-                         p = p->down;
-                         while (p->right)
-                           p = p->right;
+                         _asn1_append_sequence_set (p, &ptail);
+                         p = ptail;
                          move = RIGHT;
                          continue;
                        }
 
-                     _asn1_set_value (p, NULL, 0);
+                     p->tmp_ival = 0;
+                     ptail = NULL; /* finished decoding this structure */
                      DECR_LEN(ider_len, 2);
                      counter += 2;
                    }
@@ -1302,15 +1308,15 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                    {           /* definite length method */
                      if (len2 > counter)
                        {
-                         _asn1_append_sequence_set (p);
-                         p = p->down;
-                         while (p->right)
-                           p = p->right;
+                         _asn1_append_sequence_set (p, &ptail);
+                         p = ptail;
                          move = RIGHT;
                          continue;
                        }
 
-                     _asn1_set_value (p, NULL, 0);
+                     p->tmp_ival = 0;
+                     ptail = NULL; /* finished decoding this structure */
+
                      if (len2 != counter)
                        {
                          result = ASN1_DER_ERROR;
@@ -1336,22 +1342,18 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
                    {
                      if (len3 > 0)
                        {       /* definite length method */
-                         _asn1_ltostr (counter + len3, temp);
-                         tlen = strlen (temp);
-
-                         if (tlen > 0)
-                           _asn1_set_value (p, temp, tlen + 1);
+                         p->tmp_ival = counter + len3;
                        }
                      else
                        {       /* indefinite length method */
-                         _asn1_set_value (p, "-1", 3);
+                         p->tmp_ival = -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);
+                       _asn1_append_sequence_set (p, &ptail);
                      p = p2;
                    }
                }
@@ -1440,6 +1442,11 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
            }
        }
 
+      if (p)
+        {
+         p->end = counter - 1;
+        }
+
       if (p == node && move != DOWN)
        break;
 
@@ -1458,18 +1465,21 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   _asn1_delete_not_used (*element);
 
-  if (ider_len != 0)
+  if ((ider_len < 0) ||
+      (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0)))
     {
       warn();
       result = ASN1_DER_ERROR;
       goto cleanup;
     }
 
+  *max_ider_len = total_len - ider_len;
+
   return ASN1_SUCCESS;
 
 cleanup:
@@ -1477,6 +1487,34 @@ cleanup:
   return result;
 }
 
+
+/**
+ * asn1_der_decoding:
+ * @element: pointer to an ASN1 structure.
+ * @ider: vector that contains the DER encoding.
+ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+ * @errorDescription: null-terminated string contains details when an
+ *   error occurred.
+ *
+ * Fill the structure *@element with values of a DER encoding
+ * string. The structure must just be created with function
+ * asn1_create_element(). 
+ *
+ * Note that the *@element variable is provided as a pointer for
+ * historical reasons.
+ *
+ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+ *   if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+ *   %ASN1_DER_ERROR if the der encoding doesn't match the structure
+ *   name (*@ELEMENT deleted).
+ **/
+int
+asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
+                  char *errorDescription)
+{
+  return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
+}
+
 #define FOUND        1
 #define SAME_BRANCH  2
 #define OTHER_BRANCH 3
@@ -1533,6 +1571,9 @@ asn1_der_decoding_element (asn1_node * structure, const char *elementName,
  * One example is the sequence "tbsCertificate" inside an X509
  * certificate.
  *
+ * Note that since libtasn1 3.7 the @ider and @ider_len parameters
+ * can be omitted, if the element is already decoded using asn1_der_decoding().
+ *
  * 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
@@ -1542,12 +1583,8 @@ 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 = ASN1_DER_ERROR;
-  const unsigned char *der = ider;
+  asn1_node node, node_to_find;
+  int result = ASN1_DER_ERROR;
 
   node = element;
 
@@ -1559,377 +1596,34 @@ asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len,
   if (node_to_find == NULL)
     return ASN1_ELEMENT_NOT_FOUND;
 
-  if (node_to_find == node)
-    {
-      *start = 0;
-      *end = ider_len - 1;
-      return ASN1_SUCCESS;
-    }
-
-  if (node->type & CONST_OPTION)
-    return ASN1_GENERIC_ERROR;
+  *start = node_to_find->start;
+  *end = node_to_find->end;
 
-  counter = 0;
-  move = DOWN;
-  p = node;
-  while (1)
+  if (*start == 0 && *end == 0)
     {
-      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)
-               {
-                 warn();
-                 return ASN1_DER_ERROR;
-               }
-
-             len2 = _asn1_strtol (p2->value, NULL, 10);
-             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)
-               {
-                 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,
-                                                ider_len, &len2);
-                     if (ris == ASN1_SUCCESS)
-                       {
-                         p2->type &= ~CONST_NOT_USED;
-                         p = p2;
-                         break;
-                       }
-                   }
-                 p2 = p2->right;
-               }
-             if (p2 == NULL)
-               {
-                 warn();
-                 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)
-               {
-                 warn();
-                 return ASN1_DER_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, ider_len, &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
-               {
-                 warn();
-                 return ASN1_TAG_ERROR;
-               }
-           }
-         else
-           {
-             DECR_LEN(ider_len, len2);
-             counter += len2;
-           }
-       }
-
-      if (ris == ASN1_SUCCESS)
-       {
-         switch (type_field (p->type))
-           {
-           case ASN1_ETYPE_NULL:
-              DECR_LEN(ider_len, 1);
-
-             if (der[counter])
-               {
-                 warn();
-                 return ASN1_DER_ERROR;
-               }
-             counter++;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_BOOLEAN:
-              DECR_LEN(ider_len, 2);
-
-             if (der[counter] != 1)
-               {
-                 warn();
-                 return ASN1_DER_ERROR;
-               }
-
-             counter += 2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_OCTET_STRING:
-             ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3);
-             if (ris != ASN1_SUCCESS)
-               {
-                 warn();
-                 return ris;
-               }
-              DECR_LEN(ider_len, len3);
-             counter += len3;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_UTC_TIME:
-           case ASN1_ETYPE_GENERALIZED_TIME:
-           case ASN1_ETYPE_OBJECT_ID:
-           case ASN1_ETYPE_INTEGER:
-           case ASN1_ETYPE_ENUMERATED:
-           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, ider_len, &len3);
-             if (len2 < 0)
-               {
-                 warn();
-                 return ASN1_DER_ERROR;
-               }
-
-              DECR_LEN(ider_len, len3 + len2);
-             counter += len3 + len2;
-             move = RIGHT;
-             break;
-           case ASN1_ETYPE_SEQUENCE:
-           case ASN1_ETYPE_SET:
-             if (move != UP)
-               {
-                 len3 =
-                   asn1_get_length_der (der + counter, ider_len, &len2);
-                 if (len3 < -1)
-                   {
-                     warn();
-                     return ASN1_DER_ERROR;
-                   }
-
-                  DECR_LEN(ider_len, len2);
-                 counter += len2;
-
-                 if (len3 == 0)
-                   move = RIGHT;
-                 else
-                   move = DOWN;
-               }
-             else
-               {
-                 if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) /* indefinite length method */
-                   {
-                     counter += 2;
-                     DECR_LEN(ider_len, 2);
-                   }
-                 move = RIGHT;
-               }
-             break;
-           case ASN1_ETYPE_SEQUENCE_OF:
-           case ASN1_ETYPE_SET_OF:
-             if (move != UP)
-               {
-                 len3 =
-                   asn1_get_length_der (der + counter, ider_len, &len2);
-                 if (len3 < -1)
-                   {
-                     warn();
-                     return ASN1_DER_ERROR;
-                   }
-
-                  DECR_LEN(ider_len, len2);
-                 counter += len2;
-
-                 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) ||
-                            (type_field (p2->type) == ASN1_ETYPE_SIZE))
-                       p2 = p2->right;
-                     p = p2;
-                   }
-               }
-             else
-               {
-                 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, ider_len, &class, &len2,
-                  &tag) != ASN1_SUCCESS)
-                {
-                   warn();
-                   return ASN1_DER_ERROR;
-                }
-
-             DECR_LEN(ider_len, len2);
+      if (ider == NULL || ider_len == 0)
+        return ASN1_GENERIC_ERROR;
 
-             len4 =
-               asn1_get_length_der (der + counter + len2,
-                                    ider_len, &len3);
-             if (len4 < -1)
-               {
-                 warn();
-                 return ASN1_DER_ERROR;
-               }
-
-             if (len4 != -1)
-               {
-                 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;
-
-                 ris =
-                   _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
-                 if (ris != ASN1_SUCCESS)
-                   {
-                     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
-                       {
-                         warn();
-                         return ASN1_DER_ERROR;
-                       }
-                   }
-               }
-             move = RIGHT;
-             break;
-           default:
-             move = (move == UP) ? RIGHT : DOWN;
-             break;
-           }
-       }
-
-      if ((p == node_to_find) && (move == RIGHT))
-       {
-         *end = counter - 1;
-         return ASN1_SUCCESS;
-       }
+      /* it seems asn1_der_decoding() wasn't called before. Do it now */
+      result = asn1_der_decoding (&node, ider, ider_len, NULL);
+      if (result != ASN1_SUCCESS)
+        {
+          warn();
+          return result;
+        }
 
-      if (p == node && move != DOWN)
-       break;
+      node_to_find = asn1_find_node (node, name_element);
+      if (node_to_find == NULL)
+        return ASN1_ELEMENT_NOT_FOUND;
 
-      if (move == DOWN)
-       {
-         if (p->down)
-           p = p->down;
-         else
-           move = RIGHT;
-       }
-      if ((move == RIGHT) && !(p->type & CONST_SET))
-       {
-         if (p->right)
-           p = p->right;
-         else
-           move = UP;
-       }
-      if (move == UP)
-       p = _asn1_find_up (p);
+      *start = node_to_find->start;
+      *end = node_to_find->end;
     }
 
-  warn();
-  return ASN1_ELEMENT_NOT_FOUND;
+  if (*end < *start)
+    return ASN1_GENERIC_ERROR;
 
-cleanup:
-  return result;
+  return ASN1_SUCCESS;
 }
 
 /**
@@ -1984,7 +1678,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
                  break;
                }
 
-             p3 = _asn1_find_up (p);
+             p3 = _asn1_get_up (p);
 
              if (!p3)
                {
@@ -2004,8 +1698,8 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
                  (p3->value == NULL))
                {
 
-                 p3 = _asn1_find_up (p);
-                 p3 = _asn1_find_up (p3);
+                 p3 = _asn1_get_up (p);
+                 p3 = _asn1_get_up (p3);
 
                  if (!p3)
                    {
@@ -2140,7 +1834,7 @@ asn1_expand_any_defined_by (asn1_node definitions, asn1_node * element)
        {
          while (1)
            {
-             p = _asn1_find_up (p);
+             p = _asn1_get_up (p);
              if (p == *element)
                {
                  p = NULL;
index ac30e46610160fdbaef92c7920e7ce8ba6125e49..321302af06fa6d2b171f4cea269dd2473c074879 100644 (file)
@@ -52,7 +52,7 @@ _asn1_hierarchical_name (asn1_node node, char *name, int name_size)
          _asn1_str_cat (name, name_size, ".");
          _asn1_str_cat (name, name_size, tmp_name);
        }
-      p = _asn1_find_up (p);
+      p = _asn1_get_up (p);
     }
 
   if (name[0] == 0)
@@ -128,9 +128,18 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
   return ASN1_SUCCESS;
 }
 
-
+/* Appends a new element into the sequent (or set) defined by this
+ * node. The new element will have a name of '?number', where number
+ * is a monotonically increased serial number.
+ *
+ * The last element in the list may be provided in @ptail, to avoid
+ * traversing the list, an expensive operation in long lists.
+ *
+ * On success it returns in @ptail the added element (which is the 
+ * tail in the list of added elements).
+ */
 int
-_asn1_append_sequence_set (asn1_node node)
+_asn1_append_sequence_set (asn1_node node, asn1_node *ptail)
 {
   asn1_node p, p2;
   char temp[LTOSTR_MAX_SIZE];
@@ -144,9 +153,19 @@ _asn1_append_sequence_set (asn1_node node)
         || (type_field (p->type) == ASN1_ETYPE_SIZE))
     p = p->right;
   p2 = _asn1_copy_structure3 (p);
-  while (p->right)
-    p = p->right;
+
+  if (ptail == NULL || *ptail == NULL || (*ptail)->up != p->up)
+    while (p->right) {
+      p = p->right;
+    }
+  else
+    {
+      p = *ptail;
+    }
+
   _asn1_set_right (p, p2);
+  if (ptail)
+    *ptail = p2;
 
   if (p->name[0] == 0)
     _asn1_str_cpy (temp, sizeof (temp), "?1");
@@ -608,7 +627,7 @@ asn1_write_value (asn1_node node_root, const char *name,
     case ASN1_ETYPE_SET_OF:
       if (_asn1_strcmp (value, "NEW"))
        return ASN1_VALUE_NOT_VALID;
-      _asn1_append_sequence_set (node);
+      _asn1_append_sequence_set (node, NULL);
       break;
     default:
       return ASN1_ELEMENT_NOT_FOUND;
@@ -676,7 +695,9 @@ asn1_write_value (asn1_node node_root, const char *name,
  * %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.
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
  *
  * Note that there can be valid values with length zero. In these case
  * this function will succeed and @len will be zero.
@@ -741,12 +762,14 @@ asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
  *   holds the sizeof value.
  * @etype: The type of the value read (ASN1_ETYPE)
  *
- * Returns the value of one element inside a structure. 
+ * Returns the type and 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.
+ * so on. If the @root provided is a node to specific sequence element,
+ * then the keyword "?CURRENT" is also acceptable and indicates the
+ * current sequence element of this node.
  *
  * Note that there can be valid values with length zero. In these case
  * this function will succeed and @len will be zero.
index fdecafb611ec3b8f6d658292198a1beadee3cb71..65a484569953dd6246043ac11dd25513542781fc 100644 (file)
@@ -23,7 +23,7 @@
 #define _ELEMENT_H
 
 
-int _asn1_append_sequence_set (asn1_node node);
+int _asn1_append_sequence_set (asn1_node node, asn1_node *pcached);
 
 int _asn1_convert_integer (const unsigned char *value,
                           unsigned char *value_out,
index 3701e5f6458078d363eb1689df4225b56fcff3d7..8cc79cca2e61d57823ddef2bba86c4c38ff5dcb9 100644 (file)
@@ -51,11 +51,17 @@ struct asn1_node_st
   unsigned int type;           /* Node type */
   unsigned char *value;                /* Node value */
   int value_len;
+  asn1_node up;                        /* Pointer to the parent node */
   asn1_node down;              /* Pointer to the son node */
   asn1_node right;             /* Pointer to the brother node */
   asn1_node left;              /* Pointer to the next list element */
   /* private fields: */
   unsigned char small_value[ASN1_SMALL_VALUE_SIZE];    /* For small values */
+
+  /* values used during decoding/coding */
+  int tmp_ival;
+  unsigned start; /* the start of the DER sequence - if decoded */
+  unsigned end; /* the end of the DER sequence - if decoded */
 };
 
 typedef struct tag_and_class_st
index a4570682e0b54eb9c0ad38903f719e267ec1d445..8f7ff0b262a775fd2a77d063c27c6268bfb68c1e 100644 (file)
@@ -44,7 +44,7 @@ extern "C"
 {
 #endif
 
-#define ASN1_VERSION "3.6"
+#define ASN1_VERSION "4.0"
 
 #if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
 # define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
@@ -184,6 +184,9 @@ extern "C"
 /* makes sure the values are zeroized prior to deinitialization */
 #define ASN1_DELETE_FLAG_ZEROIZE 1
 
+/* Flags used by asn1_der_decoding2(). */
+#define ASN1_DECODE_FLAG_ALLOW_PADDING 1
+
 
   struct asn1_data_node_st
   {
@@ -258,6 +261,11 @@ extern "C"
     asn1_der_coding (asn1_node element, const char *name,
                     void *ider, int *len, char *ErrorDescription);
 
+  extern ASN1_API int
+    asn1_der_decoding2 (asn1_node *element, const void *ider,
+                       int *max_ider_len, unsigned int flags,
+                       char *errorDescription);
+
   extern ASN1_API int
     asn1_der_decoding (asn1_node * element, const void *ider,
                       int len, char *errorDescription);
@@ -329,6 +337,8 @@ extern "C"
   extern ASN1_API int
     asn1_copy_node (asn1_node dst, const char *dst_name,
                    asn1_node src, const char *src_name);
+  extern ASN1_API asn1_node
+    asn1_dup_node (asn1_node src, const char *src_name);
 
   /* Internal and low-level DER utility functions. */
 
index effedb23661a9bc4c5d90677f9915ddd2d2b0636..4b150009aae85a1e23e4f46408d54cc73dcf6075 100644 (file)
@@ -108,7 +108,13 @@ asn1_find_node (asn1_node pointer, const char *name)
   p = pointer;
   n_start = name;
 
-  if (p->name[0] != 0)
+  if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?')
+    { /* ?CURRENT */
+      n_start = strchr(n_start, '.');
+      if (n_start)
+        n_start++;
+    }
+  else if (p->name[0] != 0)
     {                          /* has *pointer got a name ? */
       n_end = strchr (n_start, '.');   /* search the first dot */
       if (n_end)
@@ -170,13 +176,13 @@ asn1_find_node (asn1_node pointer, const char *name)
        return NULL;
 
       p = p->down;
+      if (p == NULL)
+        return NULL;
 
       /* The identifier "?LAST" indicates the last element
          in the right chain. */
-      if (!strcmp (n, "?LAST"))
+      if (n[0] == '?' && n[1] == 'L') /* ?LAST */
        {
-         if (p == NULL)
-           return NULL;
          while (p->right)
            p = p->right;
        }
@@ -189,9 +195,9 @@ asn1_find_node (asn1_node pointer, const char *name)
              else
                p = p->right;
            }
-         if (p == NULL)
-           return NULL;
        }
+      if (p == NULL)
+        return NULL;
     }                          /* while */
 
   return p;
@@ -419,7 +425,11 @@ _asn1_set_right (asn1_node node, asn1_node right)
     return node;
   node->right = right;
   if (right)
-    right->left = node;
+    {
+      right->left = node;
+      if (right->up == NULL)
+        right->up = node->up;
+    }
   return node;
 }
 
@@ -615,7 +625,7 @@ _asn1_change_integer_value (asn1_node node)
            {
              while (1)
                {
-                 p = _asn1_find_up (p);
+                 p = _asn1_get_up (p);
                  if (p == node)
                    {
                      p = NULL;
@@ -740,7 +750,7 @@ _asn1_expand_object_id (asn1_node node)
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
 
@@ -812,7 +822,7 @@ _asn1_expand_object_id (asn1_node node)
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   return ASN1_SUCCESS;
@@ -882,7 +892,7 @@ _asn1_type_set_config (asn1_node node)
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   return ASN1_SUCCESS;
@@ -979,7 +989,7 @@ _asn1_check_identifier (asn1_node node)
        {
          while (1)
            {
-             p = _asn1_find_up (p);
+             p = _asn1_get_up (p);
              if (p == node)
                {
                  p = NULL;
@@ -1039,7 +1049,7 @@ _asn1_set_default_tag (asn1_node node)
        {
          while (1)
            {
-             p = _asn1_find_up (p);
+             p = _asn1_get_up (p);
              if (p == node)
                {
                  p = NULL;
index 1f1aec26375b929d1b125be0195525292f389340..55d9061917a7ce59854faa6f7f1d7df32efaad84 100644 (file)
@@ -57,6 +57,14 @@ char *_asn1_ltostr (long v, char *str);
 
 asn1_node _asn1_find_up (asn1_node node);
 
+inline static asn1_node _asn1_get_up(asn1_node node)
+{
+       if (node && node->up)
+               return node->up;
+       else
+               return _asn1_find_up(node);
+}
+
 int _asn1_change_integer_value (asn1_node node);
 
 int _asn1_expand_object_id (asn1_node node);
@@ -99,7 +107,10 @@ _asn1_set_down (asn1_node node, asn1_node down)
     return node;
   node->down = down;
   if (down)
-    down->left = node;
+    {
+      down->left = node;
+      down->up = node;
+    }
   return node;
 }
 
index 27fbfe3a226d892df092cf5188c0d38ebcc9ec36..ffb6aa50922dd7a63a5985afebe404b86ab1a506 100644 (file)
@@ -134,7 +134,7 @@ _asn1_create_static_structure (asn1_node pointer, char *output_file_name,
        {
          while (1)
            {
-             p = _asn1_find_up (p);
+             p = _asn1_get_up (p);
              if (p == pointer)
                {
                  p = NULL;
@@ -221,7 +221,7 @@ asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
              if (p_last == *definitions)
                break;
 
-             p_last = _asn1_find_up (p_last);
+             p_last = _asn1_get_up (p_last);
 
              if (p_last == NULL)
                break;
@@ -321,7 +321,7 @@ asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
          p2 = p->right;
          if (p != *structure)
            {
-             p3 = _asn1_find_up (p);
+             p3 = _asn1_get_up (p);
              _asn1_set_down (p3, p2);
              _asn1_remove_node (p, flags);
              p = p3;
@@ -331,7 +331,7 @@ asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
              p3 = _asn1_find_left (p);
              if (!p3)
                {
-                 p3 = _asn1_find_up (p);
+                 p3 = _asn1_get_up (p);
                  if (p3)
                    _asn1_set_down (p3, p2);
                  else
@@ -379,7 +379,7 @@ asn1_delete_element (asn1_node structure, const char *element_name)
   p3 = _asn1_find_left (source_node);
   if (!p3)
     {
-      p3 = _asn1_find_up (source_node);
+      p3 = _asn1_get_up (source_node);
       if (p3)
        _asn1_set_down (p3, p2);
       else if (source_node->right)
@@ -423,6 +423,8 @@ _asn1_copy_structure3 (asn1_node source_node)
              _asn1_set_down (p_d_prev, p_d);
              continue;
            }
+         p_d->start = p_s->start;
+         p_d->end = p_s->end;
        }
 
       if (p_s == source_node)
@@ -439,8 +441,8 @@ _asn1_copy_structure3 (asn1_node source_node)
       else
        {
          move = UP;
-         p_s = _asn1_find_up (p_s);
-         p_d = _asn1_find_up (p_d);
+         p_s = _asn1_get_up (p_s);
+         p_d = _asn1_get_up (p_d);
        }
     }
   while (p_s != source_node);
@@ -540,7 +542,7 @@ _asn1_type_choice_config (asn1_node node)
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   return ASN1_SUCCESS;
@@ -591,7 +593,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
                _asn1_set_right (p3, p2);
              else
                {
-                 p3 = _asn1_find_up (p);
+                 p3 = _asn1_get_up (p);
                  if (p3)
                    _asn1_set_down (p3, p2);
                  else
@@ -647,7 +649,7 @@ _asn1_expand_identifier (asn1_node * node, asn1_node root)
            move = UP;
        }
       if (move == UP)
-       p = _asn1_find_up (p);
+       p = _asn1_get_up (p);
     }
 
   return ASN1_SUCCESS;
@@ -1015,7 +1017,7 @@ asn1_print_structure (FILE * out, asn1_node structure, const char *name,
        {
          while (1)
            {
-             p = _asn1_find_up (p);
+             p = _asn1_get_up (p);
              if (p == root)
                {
                  p = NULL;
@@ -1128,12 +1130,13 @@ asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
 
 /**
  * asn1_copy_node:
- * @dst: Destination asn1_node node.
+ * @dst: Destination asn1 node.
  * @dst_name: Field name in destination node.
- * @src: Source asn1_node node.
+ * @src: Source asn1 node.
  * @src_name: Field name in source node.
  *
- * Create a deep copy of a asn1_node variable.
+ * Create a deep copy of a asn1_node variable. That
+ * function requires @dst to be expanded using asn1_create_element().
  *
  * Returns: Return %ASN1_SUCCESS on success.
  **/
@@ -1141,9 +1144,6 @@ int
 asn1_copy_node (asn1_node dst, const char *dst_name,
                asn1_node src, const char *src_name)
 {
-/* FIXME: rewrite using copy_structure().
- * It seems quite hard to do.
- */
   int result;
   asn1_node dst_node;
   void *data = NULL;
@@ -1177,3 +1177,19 @@ asn1_copy_node (asn1_node dst, const char *dst_name,
 
   return result;
 }
+
+/**
+ * asn1_dup_node:
+ * @src: Source asn1 node.
+ * @src_name: Field name in source node.
+ *
+ * Create a deep copy of a asn1_node variable. This function
+ * will return an exact copy of the provided structure.
+ *
+ * Returns: Return %NULL on failure.
+ **/
+asn1_node
+asn1_dup_node (asn1_node src, const char *src_name)
+{
+  return _asn1_copy_structure2(src, src_name);
+}