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 <hash-pjw-bare.h>
24 #include "parser_aux.h"
26 #include "structure.h"
29 char _asn1_identifierMissing
[ASN1_MAX_NAME_SIZE
+ 1]; /* identifier name not found */
31 /***********************************************/
33 /* Description: type used in the list during */
34 /* the structure creation. */
35 /***********************************************/
36 typedef struct list_struct
39 struct list_struct
*next
;
43 /* Pointer to the first element of the list */
44 list_type
*firstElement
= NULL
;
46 /******************************************************/
47 /* Function : _asn1_add_static_node */
48 /* Description: creates a new NODE_ASN element and */
49 /* puts it in the list pointed by firstElement. */
51 /* type: type of the new element (see ASN1_ETYPE_ */
52 /* and CONST_ constants). */
53 /* Return: pointer to the new element. */
54 /******************************************************/
56 _asn1_add_static_node (unsigned int type
)
58 list_type
*listElement
;
61 punt
= calloc (1, sizeof (struct asn1_node_st
));
65 listElement
= malloc (sizeof (list_type
));
66 if (listElement
== NULL
)
72 listElement
->node
= punt
;
73 listElement
->next
= firstElement
;
74 firstElement
= listElement
;
83 * @pointer: NODE_ASN element pointer.
84 * @name: null terminated string with the element's name to find.
86 * Searches for an element called @name starting from @pointer. The
87 * name is composed by differents identifiers separated by dots. When
88 * *@pointer has a name, the first identifier must be the name of
89 * *@pointer, otherwise it must be the name of one child of *@pointer.
91 * Returns: the search result, or %NULL if not found.
94 asn1_find_node (asn1_node pointer
, const char *name
)
97 char *n_end
, n
[ASN1_MAX_NAME_SIZE
+ 1];
112 { /* has *pointer got a name ? */
113 n_end
= strchr (n_start
, '.'); /* search the first dot */
116 nsize
= n_end
- n_start
;
117 memcpy (n
, n_start
, nsize
);
122 nhash
= hash_pjw_bare(n
, nsize
);
126 nsize
= _asn1_str_cpy (n
, sizeof (n
), n_start
);
127 nhash
= hash_pjw_bare(n
, nsize
);
134 if ((p
->name
) && nhash
== p
->name_hash
&& (!strcmp (p
->name
, n
)))
144 { /* *pointer doesn't have a name */
150 { /* Has the end of NAME been reached? */
151 n_end
= strchr (n_start
, '.'); /* search the next dot */
154 nsize
= n_end
- n_start
;
155 memcpy (n
, n_start
, nsize
);
160 nhash
= hash_pjw_bare(n
, nsize
);
164 nsize
= _asn1_str_cpy (n
, sizeof (n
), n_start
);
165 nhash
= hash_pjw_bare(n
, nsize
);
174 /* The identifier "?LAST" indicates the last element
175 in the right chain. */
176 if (!strcmp (n
, "?LAST"))
187 if (p
->name_hash
== nhash
&& !strcmp (p
->name
, n
))
201 /******************************************************************/
202 /* Function : _asn1_set_value */
203 /* Description: sets the field VALUE in a NODE_ASN element. The */
204 /* previous value (if exist) will be lost */
206 /* node: element pointer. */
207 /* value: pointer to the value that you want to set. */
208 /* len: character number of value. */
209 /* Return: pointer to the NODE_ASN element. */
210 /******************************************************************/
212 _asn1_set_value (asn1_node node
, const void *value
, unsigned int len
)
218 if (node
->value
!= node
->small_value
)
227 if (len
< sizeof (node
->small_value
))
229 node
->value
= node
->small_value
;
233 node
->value
= malloc (len
);
234 if (node
->value
== NULL
)
237 node
->value_len
= len
;
239 memcpy (node
->value
, value
, len
);
243 /******************************************************************/
244 /* Function : _asn1_set_value_lv */
245 /* Description: sets the field VALUE in a NODE_ASN element. The */
246 /* previous value (if exist) will be lost. The value */
247 /* given is stored as an length-value format (LV */
249 /* node: element pointer. */
250 /* value: pointer to the value that you want to set. */
251 /* len: character number of value. */
252 /* Return: pointer to the NODE_ASN element. */
253 /******************************************************************/
255 _asn1_set_value_lv (asn1_node node
, const void *value
, unsigned int len
)
263 asn1_length_der (len
, NULL
, &len2
);
264 temp
= malloc (len
+ len2
);
268 asn1_octet_der (value
, len
, temp
, &len2
);
269 return _asn1_set_value_m (node
, temp
, len2
);
272 /* the same as _asn1_set_value except that it sets an already malloc'ed
276 _asn1_set_value_m (asn1_node node
, void *value
, unsigned int len
)
283 if (node
->value
!= node
->small_value
)
293 node
->value_len
= len
;
298 /******************************************************************/
299 /* Function : _asn1_append_value */
300 /* Description: appends to the field VALUE in a NODE_ASN element. */
303 /* node: element pointer. */
304 /* value: pointer to the value that you want to be appended. */
305 /* len: character number of value. */
306 /* Return: pointer to the NODE_ASN element. */
307 /******************************************************************/
309 _asn1_append_value (asn1_node node
, const void *value
, unsigned int len
)
313 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
315 /* value is allocated */
316 int prev_len
= node
->value_len
;
317 node
->value_len
+= len
;
318 node
->value
= realloc (node
->value
, node
->value_len
);
319 if (node
->value
== NULL
)
324 memcpy (&node
->value
[prev_len
], value
, len
);
328 else if (node
->value
== node
->small_value
)
330 /* value is in node */
331 int prev_len
= node
->value_len
;
332 node
->value_len
+= len
;
333 node
->value
= malloc (node
->value_len
);
334 if (node
->value
== NULL
)
339 memcpy (node
->value
, node
->small_value
, prev_len
);
340 memcpy (&node
->value
[prev_len
], value
, len
);
344 else /* node->value == NULL */
345 return _asn1_set_value (node
, value
, len
);
348 /******************************************************************/
349 /* Function : _asn1_set_name */
350 /* Description: sets the field NAME in a NODE_ASN element. The */
351 /* previous value (if exist) will be lost */
353 /* node: element pointer. */
354 /* name: a null terminated string with the name that you want */
356 /* Return: pointer to the NODE_ASN element. */
357 /******************************************************************/
359 _asn1_set_name (asn1_node node
, const char *name
)
369 node
->name_hash
= hash_pjw_bare(node
->name
, 0);
373 nsize
= _asn1_str_cpy (node
->name
, sizeof (node
->name
), name
);
374 node
->name_hash
= hash_pjw_bare(node
->name
, nsize
);
379 /******************************************************************/
380 /* Function : _asn1_cpy_name */
381 /* Description: copies the field NAME in a NODE_ASN element. */
383 /* dst: a dest element pointer. */
384 /* src: a source element pointer. */
385 /* Return: pointer to the NODE_ASN element. */
386 /******************************************************************/
388 _asn1_cpy_name (asn1_node dst
, asn1_node src
)
396 dst
->name_hash
= hash_pjw_bare(dst
->name
, 0);
400 _asn1_str_cpy (dst
->name
, sizeof (dst
->name
), src
->name
);
401 dst
->name_hash
= src
->name_hash
;
406 /******************************************************************/
407 /* Function : _asn1_set_right */
408 /* Description: sets the field RIGHT in a NODE_ASN element. */
410 /* node: element pointer. */
411 /* right: pointer to a NODE_ASN element that you want be pointed*/
413 /* Return: pointer to *NODE. */
414 /******************************************************************/
416 _asn1_set_right (asn1_node node
, asn1_node right
)
427 /******************************************************************/
428 /* Function : _asn1_get_last_right */
429 /* Description: return the last element along the right chain. */
431 /* node: starting element pointer. */
432 /* Return: pointer to the last element along the right chain. */
433 /******************************************************************/
435 _asn1_get_last_right (asn1_node node
)
447 /******************************************************************/
448 /* Function : _asn1_remove_node */
449 /* Description: gets free the memory allocated for an NODE_ASN */
450 /* element (not the elements pointed by it). */
452 /* node: NODE_ASN element pointer. */
453 /******************************************************************/
455 _asn1_remove_node (asn1_node node
)
460 if (node
->value
!= NULL
&& node
->value
!= node
->small_value
)
465 /******************************************************************/
466 /* Function : _asn1_find_up */
467 /* Description: return the father of the NODE_ASN element. */
469 /* node: NODE_ASN element pointer. */
470 /* Return: Null if not found. */
471 /******************************************************************/
473 _asn1_find_up (asn1_node node
)
482 while ((p
->left
!= NULL
) && (p
->left
->right
== p
))
488 /******************************************************************/
489 /* Function : _asn1_delete_list */
490 /* Description: deletes the list elements (not the elements */
491 /* pointed by them). */
492 /******************************************************************/
494 _asn1_delete_list (void)
496 list_type
*listElement
;
500 listElement
= firstElement
;
501 firstElement
= firstElement
->next
;
506 /******************************************************************/
507 /* Function : _asn1_delete_list_and nodes */
508 /* Description: deletes the list elements and the elements */
509 /* pointed by them. */
510 /******************************************************************/
512 _asn1_delete_list_and_nodes (void)
514 list_type
*listElement
;
518 listElement
= firstElement
;
519 firstElement
= firstElement
->next
;
520 _asn1_remove_node (listElement
->node
);
527 _asn1_ltostr (long v
, char *str
)
547 temp
[start
+ count
] = '0' + (char) r
;
553 for (k
= 0; k
< count
; k
++)
554 str
[k
+ start
] = temp
[start
+ count
- k
- 1];
555 str
[count
+ start
] = 0;
560 /******************************************************************/
561 /* Function : _asn1_change_integer_value */
562 /* Description: converts into DER coding the value assign to an */
563 /* INTEGER constant. */
565 /* node: root of an ASN1element. */
567 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
568 /* otherwise ASN1_SUCCESS */
569 /******************************************************************/
571 _asn1_change_integer_value (asn1_node node
)
574 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
575 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+ 1];
579 return ASN1_ELEMENT_NOT_FOUND
;
584 if ((type_field (p
->type
) == ASN1_ETYPE_INTEGER
) && (p
->type
& CONST_ASSIGN
))
588 _asn1_convert_integer (p
->value
, val
, sizeof (val
), &len
);
589 asn1_octet_der (val
, len
, val2
, &len
);
590 _asn1_set_value (p
, val2
, len
);
608 p
= _asn1_find_up (p
);
628 /******************************************************************/
629 /* Function : _asn1_expand_object_id */
630 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
632 /* node: root of an ASN1 element. */
634 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
635 /* otherwise ASN1_SUCCESS */
636 /******************************************************************/
638 _asn1_expand_object_id (asn1_node node
)
640 asn1_node p
, p2
, p3
, p4
, p5
;
641 char name_root
[ASN1_MAX_NAME_SIZE
], name2
[2 * ASN1_MAX_NAME_SIZE
+ 1];
645 return ASN1_ELEMENT_NOT_FOUND
;
647 _asn1_str_cpy (name_root
, sizeof (name_root
), node
->name
);
652 while (!((p
== node
) && (move
== UP
)))
656 if ((type_field (p
->type
) == ASN1_ETYPE_OBJECT_ID
)
657 && (p
->type
& CONST_ASSIGN
))
660 if (p2
&& (type_field (p2
->type
) == ASN1_ETYPE_CONSTANT
))
662 if (p2
->value
&& !isdigit (p2
->value
[0]))
664 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
665 _asn1_str_cat (name2
, sizeof (name2
), ".");
666 _asn1_str_cat (name2
, sizeof (name2
),
668 p3
= asn1_find_node (node
, name2
);
669 if (!p3
|| (type_field (p3
->type
) != ASN1_ETYPE_OBJECT_ID
) ||
670 !(p3
->type
& CONST_ASSIGN
))
671 return ASN1_ELEMENT_NOT_FOUND
;
672 _asn1_set_down (p
, p2
->right
);
673 _asn1_remove_node (p2
);
678 if (type_field (p4
->type
) == ASN1_ETYPE_CONSTANT
)
680 p5
= _asn1_add_single_node (ASN1_ETYPE_CONSTANT
);
681 _asn1_set_name (p5
, p4
->name
);
682 tlen
= _asn1_strlen (p4
->value
);
684 _asn1_set_value (p5
, p4
->value
, tlen
+ 1);
687 _asn1_set_right (p5
, p
->down
);
688 _asn1_set_down (p
, p5
);
692 _asn1_set_right (p5
, p2
->right
);
693 _asn1_set_right (p2
, p5
);
731 p
= _asn1_find_up (p
);
735 /*******************************/
737 /*******************************/
741 while (!((p
== node
) && (move
== UP
)))
745 if ((type_field (p
->type
) == ASN1_ETYPE_OBJECT_ID
) &&
746 (p
->type
& CONST_DEFAULT
))
749 if (p2
&& (type_field (p2
->type
) == ASN1_ETYPE_DEFAULT
))
751 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
752 _asn1_str_cat (name2
, sizeof (name2
), ".");
753 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
754 p3
= asn1_find_node (node
, name2
);
755 if (!p3
|| (type_field (p3
->type
) != ASN1_ETYPE_OBJECT_ID
) ||
756 !(p3
->type
& CONST_ASSIGN
))
757 return ASN1_ELEMENT_NOT_FOUND
;
762 if (type_field (p4
->type
) == ASN1_ETYPE_CONSTANT
)
765 _asn1_str_cat (name2
, sizeof (name2
), ".");
766 _asn1_str_cat (name2
, sizeof (name2
),
771 tlen
= strlen (name2
);
773 _asn1_set_value (p2
, name2
, tlen
+ 1);
803 p
= _asn1_find_up (p
);
810 /******************************************************************/
811 /* Function : _asn1_type_set_config */
812 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
813 /* in the fields of the SET elements. */
815 /* node: root of an ASN1 element. */
817 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
818 /* otherwise ASN1_SUCCESS */
819 /******************************************************************/
821 _asn1_type_set_config (asn1_node node
)
827 return ASN1_ELEMENT_NOT_FOUND
;
832 while (!((p
== node
) && (move
== UP
)))
836 if (type_field (p
->type
) == ASN1_ETYPE_SET
)
841 if (type_field (p2
->type
) != ASN1_ETYPE_TAG
)
842 p2
->type
|= CONST_SET
| CONST_NOT_USED
;
873 p
= _asn1_find_up (p
);
880 /******************************************************************/
881 /* Function : _asn1_check_identifier */
882 /* Description: checks the definitions of all the identifiers */
883 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
884 /* The _asn1_identifierMissing global variable is filled if */
887 /* node: root of an ASN1 element. */
889 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
890 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
891 /* otherwise ASN1_SUCCESS */
892 /******************************************************************/
894 _asn1_check_identifier (asn1_node node
)
897 char name2
[ASN1_MAX_NAME_SIZE
* 2 + 2];
900 return ASN1_ELEMENT_NOT_FOUND
;
905 if (type_field (p
->type
) == ASN1_ETYPE_IDENTIFIER
)
907 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
908 _asn1_str_cat (name2
, sizeof (name2
), ".");
909 _asn1_str_cat (name2
, sizeof (name2
), (char *) p
->value
);
910 p2
= asn1_find_node (node
, name2
);
914 _asn1_strcpy (_asn1_identifierMissing
, p
->value
);
916 _asn1_strcpy (_asn1_identifierMissing
, "(null)");
917 return ASN1_IDENTIFIER_NOT_FOUND
;
920 else if ((type_field (p
->type
) == ASN1_ETYPE_OBJECT_ID
) &&
921 (p
->type
& CONST_DEFAULT
))
924 if (p2
&& (type_field (p2
->type
) == ASN1_ETYPE_DEFAULT
))
926 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
927 _asn1_str_cat (name2
, sizeof (name2
), ".");
928 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
929 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
930 p2
= asn1_find_node (node
, name2
);
931 if (!p2
|| (type_field (p2
->type
) != ASN1_ETYPE_OBJECT_ID
) ||
932 !(p2
->type
& CONST_ASSIGN
))
933 return ASN1_IDENTIFIER_NOT_FOUND
;
935 _asn1_identifierMissing
[0] = 0;
938 else if ((type_field (p
->type
) == ASN1_ETYPE_OBJECT_ID
) &&
939 (p
->type
& CONST_ASSIGN
))
942 if (p2
&& (type_field (p2
->type
) == ASN1_ETYPE_CONSTANT
))
944 if (p2
->value
&& !isdigit (p2
->value
[0]))
946 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
947 _asn1_str_cat (name2
, sizeof (name2
), ".");
948 _asn1_str_cat (name2
, sizeof (name2
), (char *) p2
->value
);
949 _asn1_strcpy (_asn1_identifierMissing
, p2
->value
);
950 p2
= asn1_find_node (node
, name2
);
951 if (!p2
|| (type_field (p2
->type
) != ASN1_ETYPE_OBJECT_ID
) ||
952 !(p2
->type
& CONST_ASSIGN
))
953 return ASN1_IDENTIFIER_NOT_FOUND
;
955 _asn1_identifierMissing
[0] = 0;
970 p
= _asn1_find_up (p
);
989 /******************************************************************/
990 /* Function : _asn1_set_default_tag */
991 /* Description: sets the default IMPLICIT or EXPLICIT property in */
992 /* the tagged elements that don't have this declaration. */
994 /* node: pointer to a DEFINITIONS element. */
996 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
997 /* a DEFINITIONS element, */
998 /* otherwise ASN1_SUCCESS */
999 /******************************************************************/
1001 _asn1_set_default_tag (asn1_node node
)
1005 if ((node
== NULL
) || (type_field (node
->type
) != ASN1_ETYPE_DEFINITIONS
))
1006 return ASN1_ELEMENT_NOT_FOUND
;
1011 if ((type_field (p
->type
) == ASN1_ETYPE_TAG
) &&
1012 !(p
->type
& CONST_EXPLICIT
) && !(p
->type
& CONST_IMPLICIT
))
1014 if (node
->type
& CONST_EXPLICIT
)
1015 p
->type
|= CONST_EXPLICIT
;
1017 p
->type
|= CONST_IMPLICIT
;
1030 p
= _asn1_find_up (p
);
1045 return ASN1_SUCCESS
;