optimized _asn1_find_up().
[platform/upstream/libtasn1.git] / lib / element.c
index a0f841f..c2b7107 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2000-2014 Free Software Foundation, Inc.
  *
  * This file is part of LIBTASN1.
  *
@@ -34,9 +34,9 @@
 #include "element.h"
 
 void
-_asn1_hierarchical_name (ASN1_TYPE node, char *name, int name_size)
+_asn1_hierarchical_name (asn1_node node, char *name, int name_size)
 {
-  ASN1_TYPE p;
+  asn1_node p;
   char tmp_name[64];
 
   p = node;
@@ -52,7 +52,7 @@ _asn1_hierarchical_name (ASN1_TYPE 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)
@@ -74,7 +74,7 @@ _asn1_hierarchical_name (ASN1_TYPE node, char *name, int name_size)
 /*   len: number of significant byte of value_out.                */
 /* Return: ASN1_MEM_ERROR or ASN1_SUCCESS                         */
 /******************************************************************/
-asn1_retCode
+int
 _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
                       int value_out_size, int *len)
 {
@@ -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);
@@ -127,18 +130,18 @@ _asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
 
 
 int
-_asn1_append_sequence_set (ASN1_TYPE node)
+_asn1_append_sequence_set (asn1_node node)
 {
-  ASN1_TYPE p, p2;
-  char temp[10];
+  asn1_node p, p2;
+  char temp[LTOSTR_MAX_SIZE];
   long n;
 
   if (!node || !(node->down))
     return ASN1_GENERIC_ERROR;
 
   p = node->down;
-  while ((type_field (p->type) == TYPE_TAG)
-        || (type_field (p->type) == TYPE_SIZE))
+  while ((type_field (p->type) == ASN1_ETYPE_TAG)
+        || (type_field (p->type) == ASN1_ETYPE_SIZE))
     p = p->right;
   p2 = _asn1_copy_structure3 (p);
   while (p->right)
@@ -267,15 +270,16 @@ _asn1_append_sequence_set (ASN1_TYPE node)
  *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and
  *   %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format.
  **/
-asn1_retCode
-asn1_write_value (ASN1_TYPE node_root, const char *name,
+int
+asn1_write_value (asn1_node node_root, const char *name,
                  const void *ivalue, int len)
 {
-  ASN1_TYPE node, p, p2;
+  asn1_node node, p, p2;
   unsigned char *temp, *value_temp = NULL, *default_temp = NULL;
   int len2, k, k2, negative;
   size_t i;
   const unsigned char *value = ivalue;
+  unsigned int type;
 
   node = asn1_find_node (node_root, name);
   if (node == NULL)
@@ -287,12 +291,13 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
       return ASN1_SUCCESS;
     }
 
-  if ((type_field (node->type) == TYPE_SEQUENCE_OF) && (value == NULL)
-      && (len == 0))
+  type = type_field (node->type);
+
+  if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0))
     {
       p = node->down;
-      while ((type_field (p->type) == TYPE_TAG)
-            || (type_field (p->type) == TYPE_SIZE))
+      while ((type_field (p->type) == ASN1_ETYPE_TAG)
+            || (type_field (p->type) == ASN1_ETYPE_SIZE))
        p = p->right;
 
       while (p->right)
@@ -301,15 +306,21 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
       return ASN1_SUCCESS;
     }
 
-  switch (type_field (node->type))
+  /* Don't allow element deletion for other types */
+  if (value == NULL)
+    {
+      return ASN1_VALUE_NOT_VALID;
+    }
+
+  switch (type)
     {
-    case TYPE_BOOLEAN:
+    case ASN1_ETYPE_BOOLEAN:
       if (!_asn1_strcmp (value, "TRUE"))
        {
          if (node->type & CONST_DEFAULT)
            {
              p = node->down;
-             while (type_field (p->type) != TYPE_DEFAULT)
+             while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
                p = p->right;
              if (p->type & CONST_TRUE)
                _asn1_set_value (node, NULL, 0);
@@ -324,7 +335,7 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
          if (node->type & CONST_DEFAULT)
            {
              p = node->down;
-             while (type_field (p->type) != TYPE_DEFAULT)
+             while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
                p = p->right;
              if (p->type & CONST_FALSE)
                _asn1_set_value (node, NULL, 0);
@@ -337,14 +348,13 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
       else
        return ASN1_VALUE_NOT_VALID;
       break;
-    case TYPE_INTEGER:
-    case TYPE_ENUMERATED:
+    case ASN1_ETYPE_INTEGER:
+    case ASN1_ETYPE_ENUMERATED:
       if (len == 0)
        {
          if ((isdigit (value[0])) || (value[0] == '-'))
            {
-             value_temp =
-               (unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
+             value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
              if (value_temp == NULL)
                return ASN1_MEM_ALLOC_ERROR;
 
@@ -358,13 +368,11 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
              p = node->down;
              while (p)
                {
-                 if (type_field (p->type) == TYPE_CONSTANT)
+                 if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
                    {
                      if (!_asn1_strcmp (p->name, value))
                        {
-                         value_temp =
-                           (unsigned char *)
-                           _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
+                         value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
                          if (value_temp == NULL)
                            return ASN1_MEM_ALLOC_ERROR;
 
@@ -383,21 +391,20 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
        }
       else
        {                       /* len != 0 */
-         value_temp = (unsigned char *) _asn1_malloc (len);
+         value_temp = malloc (len);
          if (value_temp == NULL)
            return ASN1_MEM_ALLOC_ERROR;
          memcpy (value_temp, value, len);
        }
 
-
       if (value_temp[0] & 0x80)
        negative = 1;
       else
        negative = 0;
 
-      if (negative && (type_field (node->type) == TYPE_ENUMERATED))
+      if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED))
        {
-         _asn1_free (value_temp);
+         free (value_temp);
          return ASN1_VALUE_NOT_VALID;
        }
 
@@ -411,20 +418,19 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
          (!negative && (value_temp[k] & 0x80)))
        k--;
 
-      _asn1_set_value_octet (node, value_temp + k, len - k);
+      _asn1_set_value_lv (node, value_temp + k, len - k);
 
       if (node->type & CONST_DEFAULT)
        {
          p = node->down;
-         while (type_field (p->type) != TYPE_DEFAULT)
+         while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
            p = p->right;
          if ((isdigit (p->value[0])) || (p->value[0] == '-'))
            {
-             default_temp =
-               (unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
+             default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
              if (default_temp == NULL)
                {
-                 _asn1_free (value_temp);
+                 free (value_temp);
                  return ASN1_MEM_ALLOC_ERROR;
                }
 
@@ -435,22 +441,20 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
            {                   /* is an identifier like v1 */
              if (!(node->type & CONST_LIST))
                {
-                 _asn1_free (value_temp);
+                 free (value_temp);
                  return ASN1_VALUE_NOT_VALID;
                }
              p2 = node->down;
              while (p2)
                {
-                 if (type_field (p2->type) == TYPE_CONSTANT)
+                 if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
                    {
                      if (!_asn1_strcmp (p2->name, p->value))
                        {
-                         default_temp =
-                           (unsigned char *)
-                           _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
+                         default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
                          if (default_temp == NULL)
                            {
-                             _asn1_free (value_temp);
+                             free (value_temp);
                              return ASN1_MEM_ALLOC_ERROR;
                            }
 
@@ -465,7 +469,7 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
                }
              if (p2 == NULL)
                {
-                 _asn1_free (value_temp);
+                 free (value_temp);
                  return ASN1_VALUE_NOT_VALID;
                }
            }
@@ -481,18 +485,18 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
              if (k2 == len2)
                _asn1_set_value (node, NULL, 0);
            }
-         _asn1_free (default_temp);
+         free (default_temp);
        }
-      _asn1_free (value_temp);
+      free (value_temp);
       break;
-    case TYPE_OBJECT_ID:
+    case ASN1_ETYPE_OBJECT_ID:
       for (i = 0; i < _asn1_strlen (value); i++)
        if ((!isdigit (value[i])) && (value[i] != '.') && (value[i] != '+'))
          return ASN1_VALUE_NOT_VALID;
       if (node->type & CONST_DEFAULT)
        {
          p = node->down;
-         while (type_field (p->type) != TYPE_DEFAULT)
+         while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
            p = p->right;
          if (!_asn1_strcmp (value, p->value))
            {
@@ -502,67 +506,70 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
        }
       _asn1_set_value (node, value, _asn1_strlen (value) + 1);
       break;
-    case TYPE_TIME:
-      if (node->type & CONST_UTC)
-       {
-         if (_asn1_strlen (value) < 11)
+    case ASN1_ETYPE_UTC_TIME:
+      {
+       len = _asn1_strlen (value);
+       if (len < 11)
+         return ASN1_VALUE_NOT_VALID;
+       for (k = 0; k < 10; k++)
+         if (!isdigit (value[k]))
            return ASN1_VALUE_NOT_VALID;
-         for (k = 0; k < 10; k++)
-           if (!isdigit (value[k]))
+       switch (len)
+         {
+         case 11:
+           if (value[10] != 'Z')
              return ASN1_VALUE_NOT_VALID;
-         switch (_asn1_strlen (value))
-           {
-           case 11:
-             if (value[10] != 'Z')
-               return ASN1_VALUE_NOT_VALID;
-             break;
-           case 13:
-             if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
-                 (value[12] != 'Z'))
-               return ASN1_VALUE_NOT_VALID;
-             break;
-           case 15:
-             if ((value[10] != '+') && (value[10] != '-'))
-               return ASN1_VALUE_NOT_VALID;
-             for (k = 11; k < 15; k++)
-               if (!isdigit (value[k]))
-                 return ASN1_VALUE_NOT_VALID;
-             break;
-           case 17:
-             if ((!isdigit (value[10])) || (!isdigit (value[11])))
+           break;
+         case 13:
+           if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
+               (value[12] != 'Z'))
+             return ASN1_VALUE_NOT_VALID;
+           break;
+         case 15:
+           if ((value[10] != '+') && (value[10] != '-'))
+             return ASN1_VALUE_NOT_VALID;
+           for (k = 11; k < 15; k++)
+             if (!isdigit (value[k]))
                return ASN1_VALUE_NOT_VALID;
-             if ((value[12] != '+') && (value[12] != '-'))
+           break;
+         case 17:
+           if ((!isdigit (value[10])) || (!isdigit (value[11])))
+             return ASN1_VALUE_NOT_VALID;
+           if ((value[12] != '+') && (value[12] != '-'))
+             return ASN1_VALUE_NOT_VALID;
+           for (k = 13; k < 17; k++)
+             if (!isdigit (value[k]))
                return ASN1_VALUE_NOT_VALID;
-             for (k = 13; k < 17; k++)
-               if (!isdigit (value[k]))
-                 return ASN1_VALUE_NOT_VALID;
-             break;
-           default:
-             return ASN1_VALUE_NOT_FOUND;
-           }
-         _asn1_set_value (node, value, _asn1_strlen (value) + 1);
-       }
-      else
-       {                       /* GENERALIZED TIME */
-         if (value)
-           _asn1_set_value (node, value, _asn1_strlen (value) + 1);
-       }
+           break;
+         default:
+           return ASN1_VALUE_NOT_FOUND;
+         }
+       _asn1_set_value (node, value, len);
+      }
       break;
-    case TYPE_OCTET_STRING:
-      if (len == 0)
-       len = _asn1_strlen (value);
-      _asn1_set_value_octet (node, value, len);
+    case ASN1_ETYPE_GENERALIZED_TIME:
+      len = _asn1_strlen (value);
+      _asn1_set_value (node, value, len);
       break;
-    case TYPE_GENERALSTRING:
+    case ASN1_ETYPE_OCTET_STRING:
+    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:
       if (len == 0)
        len = _asn1_strlen (value);
-      _asn1_set_value_octet (node, value, len);
+      _asn1_set_value_lv (node, value, len);
       break;
-    case TYPE_BIT_STRING:
+    case ASN1_ETYPE_BIT_STRING:
       if (len == 0)
        len = _asn1_strlen (value);
       asn1_length_der ((len >> 3) + 2, NULL, &len2);
-      temp = (unsigned char *) _asn1_malloc ((len >> 3) + 2 + len2);
+      temp = malloc ((len >> 3) + 2 + len2);
       if (temp == NULL)
        return ASN1_MEM_ALLOC_ERROR;
 
@@ -570,7 +577,7 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
       _asn1_set_value_m (node, temp, len2);
       temp = NULL;
       break;
-    case TYPE_CHOICE:
+    case ASN1_ETYPE_CHOICE:
       p = node->down;
       while (p)
        {
@@ -594,11 +601,11 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
       if (!p)
        return ASN1_ELEMENT_NOT_FOUND;
       break;
-    case TYPE_ANY:
-      _asn1_set_value_octet (node, value, len);
+    case ASN1_ETYPE_ANY:
+      _asn1_set_value_lv (node, value, len);
       break;
-    case TYPE_SEQUENCE_OF:
-    case TYPE_SET_OF:
+    case ASN1_ETYPE_SEQUENCE_OF:
+    case ASN1_ETYPE_SET_OF:
       if (_asn1_strcmp (value, "NEW"))
        return ASN1_VALUE_NOT_VALID;
       _asn1_append_sequence_set (node);
@@ -617,44 +624,134 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
        if (ptr_size < data_size) { \
                return ASN1_MEM_ERROR; \
        } else { \
-               memcpy( ptr, data, data_size); \
+               if (ptr && data_size > 0) \
+                 memcpy (ptr, data, data_size); \
        }
 
 #define PUT_STR_VALUE( ptr, ptr_size, data) \
-       *len = _asn1_strlen(data) + 1; \
+       *len = _asn1_strlen (data) + 1; \
        if (ptr_size < *len) { \
                return ASN1_MEM_ERROR; \
        } else { \
                /* this strcpy is checked */ \
-               _asn1_strcpy(ptr, data); \
+               if (ptr) { \
+                 _asn1_strcpy (ptr, data); \
+               } \
        }
 
-#define ADD_STR_VALUE( ptr, ptr_size, data) \
-       *len = (int) _asn1_strlen(data) + 1; \
-       if (ptr_size < (int) _asn1_strlen(ptr)+(*len)) { \
+#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
+       *len = data_size + 1; \
+       if (ptr_size < *len) { \
                return ASN1_MEM_ERROR; \
        } else { \
-               /* this strcat is checked */ \
-               _asn1_strcat(ptr, data); \
+               /* this strcpy is checked */ \
+               if (ptr) { \
+                 if (data_size > 0) \
+                   memcpy (ptr, data, data_size); \
+                 ptr[data_size] = 0; \
+               } \
        }
 
+#define ADD_STR_VALUE( ptr, ptr_size, 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.
+ * 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.
+ *            integer=1   -> value[0]=0x01 , len=1.
+ *
+ * ENUMERATED: As INTEGER (but only with not negative numbers).
+ *
+ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
+ *   "FALSE" and LEN=5 or LEN=6.
+ *
+ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
+ *   each number separated by a dot (i.e. "1.2.3.543.1").
+ *
+ *                      LEN = strlen(VALUE)+1
+ *
+ * UTCTime: VALUE will be a null terminated string in one of these
+ *   formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
+ *   LEN=strlen(VALUE)+1.
+ *
+ * GeneralizedTime: VALUE will be a null terminated string in the
+ *   same format used to set the value.
+ *
+ * OCTET STRING: VALUE will contain the octet string and LEN will be
+ *   the number of octets.
+ *
+ * GeneralString: VALUE will contain the generalstring and LEN will
+ *   be the number of octets.
+ *
+ * BIT STRING: VALUE will contain the bit string organized by bytes
+ *   and LEN will be the number of bits.
+ *
+ * CHOICE: If NAME indicates a choice type, VALUE will specify the
+ *   alternative selected.
  *
- * If an element is OPTIONAL and the function "read_value" returns
+ * ANY: If NAME indicates an any type, VALUE will indicate the DER
+ *   encoding of the structure actually used.
+ *
+ * Returns: %ASN1_SUCCESS if value is returned,
+ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
+ *   %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
+ *   selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
+ *   to store the result, and in this case @len will contain the number of
+ *   bytes needed.
+ **/
+int
+asn1_read_value (asn1_node root, const char *name, void *ivalue, int *len)
+{
+  return asn1_read_value_type (root, name, ivalue, len, NULL);
+}
+
+/**
+ * asn1_read_value_type:
+ * @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 (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 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.
@@ -699,34 +796,40 @@ asn1_write_value (ASN1_TYPE node_root, const char *name,
  *   to store the result, and in this case @len will contain the number of
  *   bytes needed.
  **/
-asn1_retCode
-asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
+int
+asn1_read_value_type (asn1_node root, const char *name, void *ivalue,
+                     int *len, unsigned int *etype)
 {
-  ASN1_TYPE node, p, p2;
-  int len2, len3;
+  asn1_node node, p, p2;
+  int len2, len3, result;
   int value_size = *len;
   unsigned char *value = ivalue;
+  unsigned type;
 
   node = asn1_find_node (root, name);
   if (node == NULL)
     return ASN1_ELEMENT_NOT_FOUND;
 
-  if ((type_field (node->type) != TYPE_NULL) &&
-      (type_field (node->type) != TYPE_CHOICE) &&
+  type = type_field (node->type);
+
+  if ((type != ASN1_ETYPE_NULL) &&
+      (type != ASN1_ETYPE_CHOICE) &&
       !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
       (node->value == NULL))
     return ASN1_VALUE_NOT_FOUND;
 
-  switch (type_field (node->type))
+  if (etype)
+    *etype = type;
+  switch (type)
     {
-    case TYPE_NULL:
+    case ASN1_ETYPE_NULL:
       PUT_STR_VALUE (value, value_size, "NULL");
       break;
-    case TYPE_BOOLEAN:
+    case ASN1_ETYPE_BOOLEAN:
       if ((node->type & CONST_DEFAULT) && (node->value == NULL))
        {
          p = node->down;
-         while (type_field (p->type) != TYPE_DEFAULT)
+         while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
            p = p->right;
          if (p->type & CONST_TRUE)
            {
@@ -746,33 +849,35 @@ asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
          PUT_STR_VALUE (value, value_size, "FALSE");
        }
       break;
-    case TYPE_INTEGER:
-    case TYPE_ENUMERATED:
+    case ASN1_ETYPE_INTEGER:
+    case ASN1_ETYPE_ENUMERATED:
       if ((node->type & CONST_DEFAULT) && (node->value == NULL))
        {
          p = node->down;
-         while (type_field (p->type) != TYPE_DEFAULT)
+         while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
            p = p->right;
          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 */
              p2 = node->down;
              while (p2)
                {
-                 if (type_field (p2->type) == TYPE_CONSTANT)
+                 if (type_field (p2->type) == ASN1_ETYPE_CONSTANT)
                    {
                      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;
                        }
                    }
@@ -783,20 +888,23 @@ asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
       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 TYPE_OBJECT_ID:
+    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)
            {
-             if (type_field (p->type) == TYPE_CONSTANT)
+             if (type_field (p->type) == ASN1_ETYPE_CONSTANT)
                {
                  ADD_STR_VALUE (value, value_size, p->value);
                  if (p->right)
@@ -806,12 +914,12 @@ asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
                }
              p = p->right;
            }
-         *len = _asn1_strlen (value) + 1;
+         (*len)++;
        }
       else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
        {
          p = node->down;
-         while (type_field (p->type) != TYPE_DEFAULT)
+         while (type_field (p->type) != ASN1_ETYPE_DEFAULT)
            p = p->right;
          PUT_STR_VALUE (value, value_size, p->value);
        }
@@ -820,34 +928,39 @@ asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
          PUT_STR_VALUE (value, value_size, node->value);
        }
       break;
-    case TYPE_TIME:
-      PUT_STR_VALUE (value, value_size, node->value);
+    case ASN1_ETYPE_GENERALIZED_TIME:
+    case ASN1_ETYPE_UTC_TIME:
+      PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len);
       break;
-    case TYPE_OCTET_STRING:
+    case ASN1_ETYPE_OCTET_STRING:
+    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:
       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 TYPE_GENERALSTRING:
+    case ASN1_ETYPE_BIT_STRING:
       len2 = -1;
-      if (asn1_get_octet_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 TYPE_BIT_STRING:
-      len2 = -1;
-      if (asn1_get_bit_der
-         (node->value, node->value_len, &len2, value, value_size,
-          len) != ASN1_SUCCESS)
-       return ASN1_MEM_ERROR;
-      break;
-    case TYPE_CHOICE:
+    case ASN1_ETYPE_CHOICE:
       PUT_STR_VALUE (value, value_size, node->down->name);
       break;
-    case TYPE_ANY:
+    case ASN1_ETYPE_ANY:
       len3 = -1;
       len2 = asn1_get_length_der (node->value, node->value_len, &len3);
       if (len2 < 0)
@@ -877,11 +990,11 @@ asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
  * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
  *   @name is not a valid element.
  **/
-asn1_retCode
-asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
+int
+asn1_read_tag (asn1_node root, const char *name, int *tagValue,
               int *classValue)
 {
-  ASN1_TYPE node, p, pTag;
+  asn1_node node, p, pTag;
 
   node = asn1_find_node (root, name);
   if (node == NULL)
@@ -895,7 +1008,7 @@ asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
     {
       while (p)
        {
-         if (type_field (p->type) == TYPE_TAG)
+         if (type_field (p->type) == ASN1_ETYPE_TAG)
            {
              if ((p->type & CONST_IMPLICIT) && (pTag == NULL))
                pTag = p;
@@ -921,53 +1034,18 @@ asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
     }
   else
     {
+      unsigned type = type_field (node->type);
       *classValue = ASN1_CLASS_UNIVERSAL;
 
-      switch (type_field (node->type))
+      switch (type)
        {
-       case TYPE_NULL:
-         *tagValue = ASN1_TAG_NULL;
+       CASE_HANDLED_ETYPES:
+         *tagValue = _asn1_tags[type].tag;
          break;
-       case TYPE_BOOLEAN:
-         *tagValue = ASN1_TAG_BOOLEAN;
-         break;
-       case TYPE_INTEGER:
-         *tagValue = ASN1_TAG_INTEGER;
-         break;
-       case TYPE_ENUMERATED:
-         *tagValue = ASN1_TAG_ENUMERATED;
-         break;
-       case TYPE_OBJECT_ID:
-         *tagValue = ASN1_TAG_OBJECT_ID;
-         break;
-       case TYPE_TIME:
-         if (node->type & CONST_UTC)
-           {
-             *tagValue = ASN1_TAG_UTCTime;
-           }
-         else
-           *tagValue = ASN1_TAG_GENERALIZEDTime;
-         break;
-       case TYPE_OCTET_STRING:
-         *tagValue = ASN1_TAG_OCTET_STRING;
-         break;
-       case TYPE_GENERALSTRING:
-         *tagValue = ASN1_TAG_GENERALSTRING;
-         break;
-       case TYPE_BIT_STRING:
-         *tagValue = ASN1_TAG_BIT_STRING;
-         break;
-       case TYPE_SEQUENCE:
-       case TYPE_SEQUENCE_OF:
-         *tagValue = ASN1_TAG_SEQUENCE;
-         break;
-       case TYPE_SET:
-       case TYPE_SET_OF:
-         *tagValue = ASN1_TAG_SET;
-         break;
-       case TYPE_TAG:
-       case TYPE_CHOICE:
-       case TYPE_ANY:
+       case ASN1_ETYPE_TAG:
+       case ASN1_ETYPE_CHOICE:
+       case ASN1_ETYPE_ANY:
+         *tagValue = -1;
          break;
        default:
          break;
@@ -980,18 +1058,20 @@ asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
 /**
  * asn1_read_node_value:
  * @node: pointer to a node.
- * @data: a point to a node_data_struct
+ * @data: a point to a asn1_data_node_st
  *
- * Returns the value a data node inside a ASN1_TYPE structure.
+ * Returns the value a data node inside a asn1_node structure.
  * The data returned should be handled as constant values.
  *
  * Returns: %ASN1_SUCCESS if the node exists.
  **/
-asn1_retCode asn1_read_node_value (ASN1_TYPE node, ASN1_DATA_NODE* data)
+int
+asn1_read_node_value (asn1_node node, asn1_data_node_st * data)
 {
   data->name = node->name;
   data->value = node->value;
   data->value_len = node->value_len;
-  
+  data->type = type_field (node->type);
+
   return ASN1_SUCCESS;
 }