2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * This file is part of LIBTASN1.
6 * The LIBTASN1 library is free software; you can redistribute it
7 * and/or modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "parser_aux.h"
25 #include "structure.h"
28 char _asn1_identifierMissing
[ASN1_MAX_NAME_SIZE
+ 1]; /* identifier name not found */
30 /***********************************************/
32 /* Description: type used in the list during */
33 /* the structure creation. */
34 /***********************************************/
35 typedef struct list_struct
38 struct list_struct
*next
;
42 /* Pointer to the first element of the list */
43 list_type
*firstElement
= NULL
;
45 /******************************************************/
46 /* Function : _asn1_add_static_node */
47 /* Description: creates a new NODE_ASN element and */
48 /* puts it in the list pointed by firstElement. */
50 /* type: type of the new element (see TYPE_ */
51 /* and CONST_ constants). */
52 /* Return: pointer to the new element. */
53 /******************************************************/
55 _asn1_add_static_node (unsigned int type
)
57 list_type
*listElement
;
60 punt
= calloc (1, sizeof (struct node_asn_struct
));
64 listElement
= malloc (sizeof (list_type
));
65 if (listElement
== NULL
)
71 listElement
->node
= punt
;
72 listElement
->next
= firstElement
;
73 firstElement
= listElement
;
82 * @pointer: NODE_ASN element pointer.
83 * @name: null terminated string with the element's name to find.
85 * Searches for an element called @name starting from @pointer. The
86 * name is composed by differents identifiers separated by dots. When
87 * *@pointer has a name, the first identifier must be the name of
88 * *@pointer, otherwise it must be the name of one child of *@pointer.
90 * Returns: the search result, or %NULL if not found.
93 asn1_find_node (ASN1_TYPE pointer
, const char *name
)
96 char *n_end
, n
[ASN1_MAX_NAME_SIZE
+ 1];
111 { /* has *pointer got a name ? */
112 n_end
= strchr (n_start
, '.'); /* search the first dot */
115 nsize
= n_end
- n_start
;
116 memcpy (n
, n_start
, nsize
);
121 nhash
= _asn1_bhash(n
, nsize
);
125 nsize
= _asn1_str_cpy (n
, sizeof (n
), n_start
);
126 nhash
= _asn1_bhash(n
, nsize
);
133 if ((p
->name
) && nhash
== p
->name_hash
&& (!strcmp (p
->name
, n
)))
143 { /* *pointer doesn't have a name */
149 { /* Has the end of NAME been reached? */
150 n_end
= strchr (n_start
, '.'); /* search the next dot */
153 nsize
= n_end
- n_start
;
154 memcpy (n
, n_start
, nsize
);
159 nhash
= _asn1_bhash(n
, nsize
);
163 nsize
= _asn1_str_cpy (n
, sizeof (n
), n_start
);
164 nhash
= _asn1_bhash(n
, nsize
);
173 /* The identifier "?LAST" indicates the last element
174 in the right chain. */
175 if (!strcmp (n
, "?LAST"))
186 if (p
->name_hash
== nhash
&& !strcmp (p
->name
, n
))
200 /******************************************************************/
201 /* Function : _asn1_set_value */
202 /* Description: sets the field VALUE in a NODE_ASN element. The */
203 /* previous value (if exist) will be lost */
205 /* node: element pointer. */
206 /* value: pointer to the value that you want to set. */
207 /* len: character number of value. */
208 /* Return: pointer to the NODE_ASN element. */
209 /******************************************************************/
211 _asn1_set_value (ASN1_TYPE node
, const void *value
, unsigned int len
)
217 if (node
->value
!= node
->small_value
)
226 if (len
< sizeof (node
->small_value
))
228 node
->value
= node
->small_value
;
232 node
->value
= malloc (len
);
233 if (node
->value
== NULL
)
236 node
->value_len
= len
;
238 memcpy (node
->value
, value
, len
);
242 /******************************************************************/
243 /* Function : _asn1_set_value_octet */
244 /* Description: sets the field VALUE in a NODE_ASN element. The */
245 /* previous value (if exist) will be lost. The value */
246 /* given is stored as an octet string. */
248 /* node: element pointer. */
249 /* value: pointer to the value that you want to set. */
250 /* len: character number of value. */
251 /* Return: pointer to the NODE_ASN element. */
252 /******************************************************************/
254 _asn1_set_value_octet (ASN1_TYPE node
, const void *value
, unsigned int len
)
262 asn1_length_der (len
, NULL
, &len2
);
263 temp
= malloc (len
+ len2
);
267 asn1_octet_der (value
, len
, temp
, &len2
);
268 return _asn1_set_value_m (node
, temp
, len2
);
271 /* the same as _asn1_set_value except that it sets an already malloc'ed
275 _asn1_set_value_m (ASN1_TYPE node
, void *value
, unsigned int len
)
282 if (node
->value
!= node
->small_value
)
292 node
->value_len
= len
;
297 /******************************************************************/
298 /* Function : _asn1_append_value */
299 /* Description: appends to the field VALUE in a NODE_ASN element. */
302 /* node: element pointer. */
303 /* value: pointer to the value that you want to be appended. */
304 /* len: character number of value. */
305 /* Return: pointer to the NODE_ASN element. */
306 /******************************************************************/
308 _asn1_append_value (ASN1_TYPE node
, const void *value
, unsigned int len
)
312 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
314 /* value is allocated */
315 int prev_len
= node
->value_len
;
316 node
->value_len
+= len
;
317 node
->value
= realloc (node
->value
, node
->value_len
);
318 if (node
->value
== NULL
)
323 memcpy (&node
->value
[prev_len
], value
, len
);
327 else if (node
->value
== node
->small_value
)
329 /* value is in node */
330 int prev_len
= node
->value_len
;
331 node
->value_len
+= len
;
332 node
->value
= malloc (node
->value_len
);
333 if (node
->value
== NULL
)
338 memcpy (node
->value
, node
->small_value
, prev_len
);
339 memcpy (&node
->value
[prev_len
], value
, len
);
343 else /* node->value == NULL */
344 return _asn1_set_value (node
, value
, len
);
347 /******************************************************************/
348 /* Function : _asn1_set_name */
349 /* Description: sets the field NAME in a NODE_ASN element. The */
350 /* previous value (if exist) will be lost */
352 /* node: element pointer. */
353 /* name: a null terminated string with the name that you want */
355 /* Return: pointer to the NODE_ASN element. */
356 /******************************************************************/
358 _asn1_set_name (ASN1_TYPE node
, const char *name
)
368 node
->name_hash
= _asn1_bhash(node
->name
, 0);
372 nsize
= _asn1_str_cpy (node
->name
, sizeof (node
->name
), name
);
373 node
->name_hash
= _asn1_bhash(node
->name
, nsize
);
378 /******************************************************************/
379 /* Function : _asn1_cpy_name */
380 /* Description: copies the field NAME in a NODE_ASN element. */
382 /* dst: a dest element pointer. */
383 /* src: a source element pointer. */
384 /* Return: pointer to the NODE_ASN element. */
385 /******************************************************************/
387 _asn1_cpy_name (ASN1_TYPE dst
, ASN1_TYPE src
)
397 dst
->name_hash
= _asn1_bhash(dst
->name
, 0);
401 nsize
= _asn1_str_cpy (dst
->name
, sizeof (dst
->name
), src
->name
);
402 dst
->name_hash
= src
->name_hash
;
407 /******************************************************************/
408 /* Function : _asn1_set_right */
409 /* Description: sets the field RIGHT in a NODE_ASN element. */
411 /* node: element pointer. */
412 /* right: pointer to a NODE_ASN element that you want be pointed*/
414 /* Return: pointer to *NODE. */
415 /******************************************************************/
417 _asn1_set_right (ASN1_TYPE node
, ASN1_TYPE right
)
428 /******************************************************************/
429 /* Function : _asn1_get_last_right */
430 /* Description: return the last element along the right chain. */
432 /* node: starting element pointer. */
433 /* Return: pointer to the last element along the right chain. */
434 /******************************************************************/
436 _asn1_get_last_right (ASN1_TYPE node
)
448 /******************************************************************/
449 /* Function : _asn1_remove_node */
450 /* Description: gets free the memory allocated for an NODE_ASN */
451 /* element (not the elements pointed by it). */
453 /* node: NODE_ASN element pointer. */
454 /******************************************************************/
456 _asn1_remove_node (ASN1_TYPE node
)
461 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
466 /******************************************************************/
467 /* Function : _asn1_find_up */
468 /* Description: return the father of the NODE_ASN element. */
470 /* node: NODE_ASN element pointer. */
471 /* Return: Null if not found. */
472 /******************************************************************/
474 _asn1_find_up (ASN1_TYPE node
)
483 while ((p
->left
!= NULL
) && (p
->left
->right
== p
))
489 /******************************************************************/
490 /* Function : _asn1_delete_list */
491 /* Description: deletes the list elements (not the elements */
492 /* pointed by them). */
493 /******************************************************************/
495 _asn1_delete_list (void)
497 list_type
*listElement
;
501 listElement
= firstElement
;
502 firstElement
= firstElement
->next
;
507 /******************************************************************/
508 /* Function : _asn1_delete_list_and nodes */
509 /* Description: deletes the list elements and the elements */
510 /* pointed by them. */
511 /******************************************************************/
513 _asn1_delete_list_and_nodes (void)
515 list_type
*listElement
;
519 listElement
= firstElement
;
520 firstElement
= firstElement
->next
;
521 _asn1_remove_node (listElement
->node
);
528 _asn1_ltostr (long v
, char *str
)
548 temp
[start
+ count
] = '0' + (char) r
;
554 for (k
= 0; k
< count
; k
++)
555 str
[k
+ start
] = temp
[start
+ count
- k
- 1];
556 str
[count
+ start
] = 0;
561 /******************************************************************/
562 /* Function : _asn1_change_integer_value */
563 /* Description: converts into DER coding the value assign to an */
564 /* INTEGER constant. */
566 /* node: root of an ASN1element. */
568 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
569 /* otherwise ASN1_SUCCESS */
570 /******************************************************************/
572 _asn1_change_integer_value (ASN1_TYPE node
)
575 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
576 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+ 1];
580 return ASN1_ELEMENT_NOT_FOUND
;
585 if ((type_field (p
->type
) == TYPE_INTEGER
) && (p
->type
& CONST_ASSIGN
))
589 _asn1_convert_integer (p
->value
, val
, sizeof (val
), &len
);
590 asn1_octet_der (val
, len
, val2
, &len
);
591 _asn1_set_value (p
, val2
, len
);
609 p
= _asn1_find_up (p
);
629 /******************************************************************/
630 /* Function : _asn1_expand_object_id */
631 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
633 /* node: root of an ASN1 element. */
635 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
636 /* otherwise ASN1_SUCCESS */
637 /******************************************************************/
639 _asn1_expand_object_id (ASN1_TYPE node
)
641 ASN1_TYPE p
, p2
, p3
, p4
, p5
;
642 char name_root
[ASN1_MAX_NAME_SIZE
], name2
[2 * ASN1_MAX_NAME_SIZE
+ 1];
646 return ASN1_ELEMENT_NOT_FOUND
;
648 _asn1_str_cpy (name_root
, sizeof (name_root
), node
->name
);
653 while (!((p
== node
) && (move
== UP
)))
657 if ((type_field (p
->type
) == TYPE_OBJECT_ID
)
658 && (p
->type
& CONST_ASSIGN
))
661 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
663 if (p2
->value
&& !isdigit (p2
->value
[0]))
665 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
666 _asn1_str_cat (name2
, sizeof (name2
), ".");
667 _asn1_str_cat (name2
, sizeof (name2
),
669 p3
= asn1_find_node (node
, name2
);
670 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
671 !(p3
->type
& CONST_ASSIGN
))
672 return ASN1_ELEMENT_NOT_FOUND
;
673 _asn1_set_down (p
, p2
->right
);
674 _asn1_remove_node (p2
);
679 if (type_field (p4
->type
) == TYPE_CONSTANT
)
681 p5
= _asn1_add_single_node (TYPE_CONSTANT
);
682 _asn1_set_name (p5
, p4
->name
);
683 tlen
= _asn1_strlen (p4
->value
);
685 _asn1_set_value (p5
, p4
->value
, tlen
+ 1);
688 _asn1_set_right (p5
, p
->down
);
689 _asn1_set_down (p
, p5
);
693 _asn1_set_right (p5
, p2
->right
);
694 _asn1_set_right (p2
, p5
);
732 p
= _asn1_find_up (p
);
736 /*******************************/
738 /*******************************/
742 while (!((p
== node
) && (move
== UP
)))
746 if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
747 (p
->type
& CONST_DEFAULT
))
750 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
752 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
753 _asn1_str_cat (name2
, sizeof (name2
), ".");
754 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
755 p3
= asn1_find_node (node
, name2
);
756 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
757 !(p3
->type
& CONST_ASSIGN
))
758 return ASN1_ELEMENT_NOT_FOUND
;
763 if (type_field (p4
->type
) == TYPE_CONSTANT
)
766 _asn1_str_cat (name2
, sizeof (name2
), ".");
767 _asn1_str_cat (name2
, sizeof (name2
),
772 tlen
= strlen (name2
);
774 _asn1_set_value (p2
, name2
, tlen
+ 1);
804 p
= _asn1_find_up (p
);
811 /******************************************************************/
812 /* Function : _asn1_type_set_config */
813 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
814 /* in the fields of the SET elements. */
816 /* node: root of an ASN1 element. */
818 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
819 /* otherwise ASN1_SUCCESS */
820 /******************************************************************/
822 _asn1_type_set_config (ASN1_TYPE node
)
828 return ASN1_ELEMENT_NOT_FOUND
;
833 while (!((p
== node
) && (move
== UP
)))
837 if (type_field (p
->type
) == TYPE_SET
)
842 if (type_field (p2
->type
) != TYPE_TAG
)
843 p2
->type
|= CONST_SET
| CONST_NOT_USED
;
874 p
= _asn1_find_up (p
);
881 /******************************************************************/
882 /* Function : _asn1_check_identifier */
883 /* Description: checks the definitions of all the identifiers */
884 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
885 /* The _asn1_identifierMissing global variable is filled if */
888 /* node: root of an ASN1 element. */
890 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
891 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
892 /* otherwise ASN1_SUCCESS */
893 /******************************************************************/
895 _asn1_check_identifier (ASN1_TYPE node
)
898 char name2
[ASN1_MAX_NAME_SIZE
* 2 + 2];
901 return ASN1_ELEMENT_NOT_FOUND
;
906 if (type_field (p
->type
) == TYPE_IDENTIFIER
)
908 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
909 _asn1_str_cat (name2
, sizeof (name2
), ".");
910 _asn1_str_cat (name2
, sizeof (name2
), (char *) p
->value
);
911 p2
= asn1_find_node (node
, name2
);
915 _asn1_strcpy (_asn1_identifierMissing
, p
->value
);
917 _asn1_strcpy (_asn1_identifierMissing
, "(null)");
918 return ASN1_IDENTIFIER_NOT_FOUND
;
921 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
922 (p
->type
& CONST_DEFAULT
))
925 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
927 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
928 _asn1_str_cat (name2
, sizeof (name2
), ".");
929 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
930 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
931 p2
= asn1_find_node (node
, name2
);
932 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
933 !(p2
->type
& CONST_ASSIGN
))
934 return ASN1_IDENTIFIER_NOT_FOUND
;
936 _asn1_identifierMissing
[0] = 0;
939 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
940 (p
->type
& CONST_ASSIGN
))
943 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
945 if (p2
->value
&& !isdigit (p2
->value
[0]))
947 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
948 _asn1_str_cat (name2
, sizeof (name2
), ".");
949 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
950 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
951 p2
= asn1_find_node (node
, name2
);
952 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
953 !(p2
->type
& CONST_ASSIGN
))
954 return ASN1_IDENTIFIER_NOT_FOUND
;
956 _asn1_identifierMissing
[0] = 0;
971 p
= _asn1_find_up (p
);
990 /******************************************************************/
991 /* Function : _asn1_set_default_tag */
992 /* Description: sets the default IMPLICIT or EXPLICIT property in */
993 /* the tagged elements that don't have this declaration. */
995 /* node: pointer to a DEFINITIONS element. */
997 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
998 /* a DEFINITIONS element, */
999 /* otherwise ASN1_SUCCESS */
1000 /******************************************************************/
1002 _asn1_set_default_tag (ASN1_TYPE node
)
1006 if ((node
== NULL
) || (type_field (node
->type
) != TYPE_DEFINITIONS
))
1007 return ASN1_ELEMENT_NOT_FOUND
;
1012 if ((type_field (p
->type
) == TYPE_TAG
) &&
1013 !(p
->type
& CONST_EXPLICIT
) && !(p
->type
& CONST_IMPLICIT
))
1015 if (node
->type
& CONST_EXPLICIT
)
1016 p
->type
|= CONST_EXPLICIT
;
1018 p
->type
|= CONST_IMPLICIT
;
1031 p
= _asn1_find_up (p
);
1046 return ASN1_SUCCESS
;