asn1_der_decoding_element is just an alias of asn1_der_decoding().
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 16 May 2014 09:04:35 +0000 (11:04 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 16 May 2014 09:04:38 +0000 (11:04 +0200)
This eliminates the need of massive code duplication.

lib/decoding.c

index 0e5077f..f6c495f 100644 (file)
@@ -1375,11 +1375,6 @@ cleanup:
   return result;
 }
 
-#define FOUND        1
-#define SAME_BRANCH  2
-#define OTHER_BRANCH 3
-#define EXIT         4
-
 /**
  * asn1_der_decoding_element:
  * @structure: pointer to an ASN1 structure
@@ -1389,13 +1384,15 @@ cleanup:
  * @errorDescription: null-terminated string contains details when an
  *   error occurred.
  *
- * Fill the element named @ELEMENTNAME with values of a DER encoding
+ * Fill the element named @elementName with values of a DER encoding
  * string.  The structure must just be created with function
  * asn1_create_element().  The DER vector must contain the encoding
- * string of the whole @STRUCTURE.  If an error occurs during the
- * decoding procedure, the *@STRUCTURE is deleted and set equal to
+ * string of the whole @structure.  If an error occurs during the
+ * decoding procedure, the *@structure is deleted and set equal to
  * %NULL.
  *
+ * As of libtasn1 3.6 this function is an alias of asn1_der_decoding().
+ *
  * 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,759 +1402,7 @@ 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;
-  unsigned char class;
-  unsigned long tag;
-  int indefinite, result;
-  const unsigned char *der = ider;
-
-  node = *structure;
-
-  if (node == NULL)
-    return ASN1_ELEMENT_NOT_FOUND;
-
-  if (elementName == NULL)
-    {
-      result = ASN1_ELEMENT_NOT_FOUND;
-      goto cleanup;
-    }
-
-  if (node->type & CONST_OPTION)
-    {
-      result = ASN1_GENERIC_ERROR;
-      goto cleanup;
-    }
-
-  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;
-       }
-    }
-
-  counter = 0;
-  move = DOWN;
-  p = node;
-  while (1)
-    {
-
-      ris = ASN1_SUCCESS;
-
-      if (move != UP)
-       {
-         if (p->type & CONST_SET)
-           {
-             p2 = _asn1_find_up (p);
-             len2 = _asn1_strtol (p2->value, NULL, 10);
-             if (counter == len2)
-               {
-                 p = p2;
-                 move = UP;
-                 continue;
-               }
-             else if (counter > len2)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-             p2 = p2->down;
-             while (p2)
-               {
-                 if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
-                   {
-                     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)
-               {
-                 result = ASN1_DER_ERROR;
-                 goto cleanup;
-               }
-           }
-
-         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 (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;
-                   }
-               }
-             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;
-           }
-
-         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)
-               {
-                 _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;
-               }
-           }
-         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;
+  return asn1_der_decoding(structure, ider, len, errorDescription);
 }
 
 /**