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_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_node (unsigned int type
)
57 list_type
*listElement
;
60 punt
= (ASN1_TYPE
) _asn1_calloc (1, sizeof (struct node_asn_struct
));
64 listElement
= (list_type
*) _asn1_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];
109 { /* has *pointer got a name ? */
110 n_end
= strchr (n_start
, '.'); /* search the first dot */
113 memcpy (n
, n_start
, n_end
- n_start
);
114 n
[n_end
- n_start
] = 0;
120 _asn1_str_cpy (n
, sizeof (n
), n_start
);
126 if ((p
->name
) && (!strcmp (p
->name
, n
)))
136 { /* *pointer doesn't have a name */
142 { /* Has the end of NAME been reached? */
143 n_end
= strchr (n_start
, '.'); /* search the next dot */
146 memcpy (n
, n_start
, n_end
- n_start
);
147 n
[n_end
- n_start
] = 0;
153 _asn1_str_cpy (n
, sizeof (n
), n_start
);
162 /* The identifier "?LAST" indicates the last element
163 in the right chain. */
164 if (!strcmp (n
, "?LAST"))
175 if ((p
->name
) && (!strcmp (p
->name
, n
)))
189 /******************************************************************/
190 /* Function : _asn1_set_value */
191 /* Description: sets the field VALUE in a NODE_ASN element. The */
192 /* previous value (if exist) will be lost */
194 /* node: element pointer. */
195 /* value: pointer to the value that you want to set. */
196 /* len: character number of value. */
197 /* Return: pointer to the NODE_ASN element. */
198 /******************************************************************/
200 _asn1_set_value (ASN1_TYPE node
, const void *value
, unsigned int len
)
206 if (node
->value
!= node
->small_value
)
207 _asn1_free (node
->value
);
215 if (len
< sizeof (node
->small_value
))
217 node
->value
= node
->small_value
;
221 node
->value
= _asn1_malloc (len
);
222 if (node
->value
== NULL
)
225 node
->value_len
= len
;
227 memcpy (node
->value
, value
, len
);
231 /******************************************************************/
232 /* Function : _asn1_set_value_octet */
233 /* Description: sets the field VALUE in a NODE_ASN element. The */
234 /* previous value (if exist) will be lost. The value */
235 /* given is stored as an octet string. */
237 /* node: element pointer. */
238 /* value: pointer to the value that you want to set. */
239 /* len: character number of value. */
240 /* Return: pointer to the NODE_ASN element. */
241 /******************************************************************/
243 _asn1_set_value_octet (ASN1_TYPE node
, const void *value
, unsigned int len
)
251 asn1_length_der (len
, NULL
, &len2
);
252 temp
= (unsigned char *) _asn1_malloc (len
+ len2
);
256 asn1_octet_der (value
, len
, temp
, &len2
);
257 return _asn1_set_value_m (node
, temp
, len2
);
260 /* the same as _asn1_set_value except that it sets an already malloc'ed
264 _asn1_set_value_m (ASN1_TYPE node
, void *value
, unsigned int len
)
271 if (node
->value
!= node
->small_value
)
272 _asn1_free (node
->value
);
281 node
->value_len
= len
;
286 /******************************************************************/
287 /* Function : _asn1_append_value */
288 /* Description: appends to the field VALUE in a NODE_ASN element. */
291 /* node: element pointer. */
292 /* value: pointer to the value that you want to be appended. */
293 /* len: character number of value. */
294 /* Return: pointer to the NODE_ASN element. */
295 /******************************************************************/
297 _asn1_append_value (ASN1_TYPE node
, const void *value
, unsigned int len
)
301 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
303 /* value is allocated */
304 int prev_len
= node
->value_len
;
305 node
->value_len
+= len
;
306 node
->value
= _asn1_realloc (node
->value
, node
->value_len
);
307 if (node
->value
== NULL
)
312 memcpy (&node
->value
[prev_len
], value
, len
);
316 else if (node
->value
== node
->small_value
)
318 /* value is in node */
319 int prev_len
= node
->value_len
;
320 node
->value_len
+= len
;
321 node
->value
= _asn1_malloc (node
->value_len
);
322 if (node
->value
== NULL
)
327 memcpy (node
->value
, node
->small_value
, prev_len
);
328 memcpy (&node
->value
[prev_len
], value
, len
);
332 else /* node->value == NULL */
333 return _asn1_set_value (node
, value
, len
);
336 /******************************************************************/
337 /* Function : _asn1_set_name */
338 /* Description: sets the field NAME in a NODE_ASN element. The */
339 /* previous value (if exist) will be lost */
341 /* node: element pointer. */
342 /* name: a null terminated string with the name that you want */
344 /* Return: pointer to the NODE_ASN element. */
345 /******************************************************************/
347 _asn1_set_name (ASN1_TYPE node
, const char *name
)
354 _asn1_free (node
->name
);
363 node
->name
= (char *) _asn1_strdup (name
);
364 if (node
->name
== NULL
)
372 /******************************************************************/
373 /* Function : _asn1_set_right */
374 /* Description: sets the field RIGHT in a NODE_ASN element. */
376 /* node: element pointer. */
377 /* right: pointer to a NODE_ASN element that you want be pointed*/
379 /* Return: pointer to *NODE. */
380 /******************************************************************/
382 _asn1_set_right (ASN1_TYPE node
, ASN1_TYPE right
)
392 /******************************************************************/
393 /* Function : _asn1_get_right */
394 /* Description: returns the element pointed by the RIGHT field of */
395 /* a NODE_ASN element. */
397 /* node: NODE_ASN element pointer. */
398 /* Return: field RIGHT of NODE. */
399 /******************************************************************/
401 _asn1_get_right (ASN1_TYPE node
)
408 /******************************************************************/
409 /* Function : _asn1_get_last_right */
410 /* Description: return the last element along the right chain. */
412 /* node: starting element pointer. */
413 /* Return: pointer to the last element along the right chain. */
414 /******************************************************************/
416 _asn1_get_last_right (ASN1_TYPE node
)
428 /******************************************************************/
429 /* Function : _asn1_set_down */
430 /* Description: sets the field DOWN in a NODE_ASN element. */
432 /* node: element pointer. */
433 /* down: pointer to a NODE_ASN element that you want be pointed */
435 /* Return: pointer to *NODE. */
436 /******************************************************************/
438 _asn1_set_down (ASN1_TYPE node
, ASN1_TYPE down
)
448 /******************************************************************/
449 /* Function : _asn1_get_down */
450 /* Description: returns the element pointed by the DOWN field of */
451 /* a NODE_ASN element. */
453 /* node: NODE_ASN element pointer. */
454 /* Return: field DOWN of NODE. */
455 /******************************************************************/
457 _asn1_get_down (ASN1_TYPE node
)
464 /******************************************************************/
465 /* Function : _asn1_get_name */
466 /* Description: returns the name of a NODE_ASN element. */
468 /* node: NODE_ASN element pointer. */
469 /* Return: a null terminated string. */
470 /******************************************************************/
472 _asn1_get_name (ASN1_TYPE node
)
479 /******************************************************************/
480 /* Function : _asn1_mod_type */
481 /* Description: change the field TYPE of an NODE_ASN element. */
482 /* The new value is the old one | (bitwise or) the */
483 /* paramener VALUE. */
485 /* node: NODE_ASN element pointer. */
486 /* value: the integer value that must be or-ed with the current */
487 /* value of field TYPE. */
488 /* Return: NODE pointer. */
489 /******************************************************************/
491 _asn1_mod_type (ASN1_TYPE node
, unsigned int value
)
500 /******************************************************************/
501 /* Function : _asn1_remove_node */
502 /* Description: gets free the memory allocated for an NODE_ASN */
503 /* element (not the elements pointed by it). */
505 /* node: NODE_ASN element pointer. */
506 /******************************************************************/
508 _asn1_remove_node (ASN1_TYPE node
)
513 if (node
->name
!= NULL
)
514 _asn1_free (node
->name
);
515 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
516 _asn1_free (node
->value
);
520 /******************************************************************/
521 /* Function : _asn1_find_up */
522 /* Description: return the father of the NODE_ASN element. */
524 /* node: NODE_ASN element pointer. */
525 /* Return: Null if not found. */
526 /******************************************************************/
528 _asn1_find_up (ASN1_TYPE node
)
537 while ((p
->left
!= NULL
) && (p
->left
->right
== p
))
543 /******************************************************************/
544 /* Function : _asn1_delete_list */
545 /* Description: deletes the list elements (not the elements */
546 /* pointed by them). */
547 /******************************************************************/
549 _asn1_delete_list (void)
551 list_type
*listElement
;
555 listElement
= firstElement
;
556 firstElement
= firstElement
->next
;
557 _asn1_free (listElement
);
561 /******************************************************************/
562 /* Function : _asn1_delete_list_and nodes */
563 /* Description: deletes the list elements and the elements */
564 /* pointed by them. */
565 /******************************************************************/
567 _asn1_delete_list_and_nodes (void)
569 list_type
*listElement
;
573 listElement
= firstElement
;
574 firstElement
= firstElement
->next
;
575 _asn1_remove_node (listElement
->node
);
576 _asn1_free (listElement
);
582 _asn1_ltostr (long v
, char *str
)
602 temp
[start
+ count
] = '0' + (char) r
;
608 for (k
= 0; k
< count
; k
++)
609 str
[k
+ start
] = temp
[start
+ count
- k
- 1];
610 str
[count
+ start
] = 0;
615 /******************************************************************/
616 /* Function : _asn1_change_integer_value */
617 /* Description: converts into DER coding the value assign to an */
618 /* INTEGER constant. */
620 /* node: root of an ASN1element. */
622 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
623 /* otherwise ASN1_SUCCESS */
624 /******************************************************************/
626 _asn1_change_integer_value (ASN1_TYPE node
)
629 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
630 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+ 1];
634 return ASN1_ELEMENT_NOT_FOUND
;
639 if ((type_field (p
->type
) == TYPE_INTEGER
) && (p
->type
& CONST_ASSIGN
))
643 _asn1_convert_integer (p
->value
, val
, sizeof (val
), &len
);
644 asn1_octet_der (val
, len
, val2
, &len
);
645 _asn1_set_value (p
, val2
, len
);
663 p
= _asn1_find_up (p
);
683 /******************************************************************/
684 /* Function : _asn1_expand_object_id */
685 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
687 /* node: root of an ASN1 element. */
689 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
690 /* otherwise ASN1_SUCCESS */
691 /******************************************************************/
693 _asn1_expand_object_id (ASN1_TYPE node
)
695 ASN1_TYPE p
, p2
, p3
, p4
, p5
;
696 char name_root
[ASN1_MAX_NAME_SIZE
], name2
[2 * ASN1_MAX_NAME_SIZE
+ 1];
700 return ASN1_ELEMENT_NOT_FOUND
;
702 _asn1_str_cpy (name_root
, sizeof (name_root
), node
->name
);
707 while (!((p
== node
) && (move
== UP
)))
711 if ((type_field (p
->type
) == TYPE_OBJECT_ID
)
712 && (p
->type
& CONST_ASSIGN
))
715 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
717 if (p2
->value
&& !isdigit (p2
->value
[0]))
719 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
720 _asn1_str_cat (name2
, sizeof (name2
), ".");
721 _asn1_str_cat (name2
, sizeof (name2
),
723 p3
= asn1_find_node (node
, name2
);
724 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
725 !(p3
->type
& CONST_ASSIGN
))
726 return ASN1_ELEMENT_NOT_FOUND
;
727 _asn1_set_down (p
, p2
->right
);
728 _asn1_remove_node (p2
);
733 if (type_field (p4
->type
) == TYPE_CONSTANT
)
735 p5
= _asn1_add_node_only (TYPE_CONSTANT
);
736 _asn1_set_name (p5
, p4
->name
);
737 tlen
= _asn1_strlen (p4
->value
);
739 _asn1_set_value (p5
, p4
->value
, tlen
+ 1);
742 _asn1_set_right (p5
, p
->down
);
743 _asn1_set_down (p
, p5
);
747 _asn1_set_right (p5
, p2
->right
);
748 _asn1_set_right (p2
, p5
);
786 p
= _asn1_find_up (p
);
790 /*******************************/
792 /*******************************/
796 while (!((p
== node
) && (move
== UP
)))
800 if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
801 (p
->type
& CONST_DEFAULT
))
804 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
806 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
807 _asn1_str_cat (name2
, sizeof (name2
), ".");
808 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
809 p3
= asn1_find_node (node
, name2
);
810 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
811 !(p3
->type
& CONST_ASSIGN
))
812 return ASN1_ELEMENT_NOT_FOUND
;
817 if (type_field (p4
->type
) == TYPE_CONSTANT
)
820 _asn1_str_cat (name2
, sizeof (name2
), ".");
821 _asn1_str_cat (name2
, sizeof (name2
),
826 tlen
= strlen (name2
);
828 _asn1_set_value (p2
, name2
, tlen
+ 1);
858 p
= _asn1_find_up (p
);
865 /******************************************************************/
866 /* Function : _asn1_type_set_config */
867 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
868 /* in the fields of the SET elements. */
870 /* node: root of an ASN1 element. */
872 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
873 /* otherwise ASN1_SUCCESS */
874 /******************************************************************/
876 _asn1_type_set_config (ASN1_TYPE node
)
882 return ASN1_ELEMENT_NOT_FOUND
;
887 while (!((p
== node
) && (move
== UP
)))
891 if (type_field (p
->type
) == TYPE_SET
)
896 if (type_field (p2
->type
) != TYPE_TAG
)
897 p2
->type
|= CONST_SET
| CONST_NOT_USED
;
928 p
= _asn1_find_up (p
);
935 /******************************************************************/
936 /* Function : _asn1_check_identifier */
937 /* Description: checks the definitions of all the identifiers */
938 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
939 /* The _asn1_identifierMissing global variable is filled if */
942 /* node: root of an ASN1 element. */
944 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
945 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
946 /* otherwise ASN1_SUCCESS */
947 /******************************************************************/
949 _asn1_check_identifier (ASN1_TYPE node
)
952 char name2
[ASN1_MAX_NAME_SIZE
* 2 + 2];
955 return ASN1_ELEMENT_NOT_FOUND
;
960 if (type_field (p
->type
) == TYPE_IDENTIFIER
)
962 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
963 _asn1_str_cat (name2
, sizeof (name2
), ".");
964 _asn1_str_cat (name2
, sizeof (name2
), (char *) p
->value
);
965 p2
= asn1_find_node (node
, name2
);
968 _asn1_strcpy (_asn1_identifierMissing
, p
->value
);
969 return ASN1_IDENTIFIER_NOT_FOUND
;
972 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
973 (p
->type
& CONST_DEFAULT
))
976 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
978 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
979 _asn1_str_cat (name2
, sizeof (name2
), ".");
980 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
981 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
982 p2
= asn1_find_node (node
, name2
);
983 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
984 !(p2
->type
& CONST_ASSIGN
))
985 return ASN1_IDENTIFIER_NOT_FOUND
;
987 _asn1_identifierMissing
[0] = 0;
990 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
991 (p
->type
& CONST_ASSIGN
))
994 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
996 if (p2
->value
&& !isdigit (p2
->value
[0]))
998 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
999 _asn1_str_cat (name2
, sizeof (name2
), ".");
1000 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
1001 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
1002 p2
= asn1_find_node (node
, name2
);
1003 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
1004 !(p2
->type
& CONST_ASSIGN
))
1005 return ASN1_IDENTIFIER_NOT_FOUND
;
1007 _asn1_identifierMissing
[0] = 0;
1022 p
= _asn1_find_up (p
);
1037 return ASN1_SUCCESS
;
1041 /******************************************************************/
1042 /* Function : _asn1_set_default_tag */
1043 /* Description: sets the default IMPLICIT or EXPLICIT property in */
1044 /* the tagged elements that don't have this declaration. */
1046 /* node: pointer to a DEFINITIONS element. */
1048 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
1049 /* a DEFINITIONS element, */
1050 /* otherwise ASN1_SUCCESS */
1051 /******************************************************************/
1053 _asn1_set_default_tag (ASN1_TYPE node
)
1057 if ((node
== NULL
) || (type_field (node
->type
) != TYPE_DEFINITIONS
))
1058 return ASN1_ELEMENT_NOT_FOUND
;
1063 if ((type_field (p
->type
) == TYPE_TAG
) &&
1064 !(p
->type
& CONST_EXPLICIT
) && !(p
->type
& CONST_IMPLICIT
))
1066 if (node
->type
& CONST_EXPLICIT
)
1067 p
->type
|= CONST_EXPLICIT
;
1069 p
->type
|= CONST_IMPLICIT
;
1082 p
= _asn1_find_up (p
);
1097 return ASN1_SUCCESS
;