2 * Copyright (C) 2004, 2006 Free Software Foundation
3 * Copyright (C) 2000,2001 Fabio Fiorina
5 * This file is part of LIBTASN1.
7 * The LIBTASN1 library is free software; you can redistribute it
8 * and/or modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "parser_aux.h"
27 #include "structure.h"
30 char _asn1_identifierMissing
[MAX_NAME_SIZE
+ 1]; /* identifier name not found */
32 /***********************************************/
34 /* Description: type used in the list during */
35 /* the structure creation. */
36 /***********************************************/
37 typedef struct list_struct
40 struct list_struct
*next
;
44 /* Pointer to the first element of the list */
45 list_type
*firstElement
= NULL
;
47 /******************************************************/
48 /* Function : _asn1_add_node */
49 /* Description: creates a new NODE_ASN element and */
50 /* puts it in the list pointed by firstElement. */
52 /* type: type of the new element (see TYPE_ */
53 /* and CONST_ constants). */
54 /* Return: pointer to the new element. */
55 /******************************************************/
57 _asn1_add_node (unsigned int type
)
59 list_type
*listElement
;
62 punt
= (node_asn
*) _asn1_calloc (1, sizeof (node_asn
));
66 listElement
= (list_type
*) _asn1_malloc (sizeof (list_type
));
67 if (listElement
== NULL
)
73 listElement
->node
= punt
;
74 listElement
->next
= firstElement
;
75 firstElement
= listElement
;
84 * @pointer: NODE_ASN element pointer.
85 * @name: null terminated string with the element's name to find.
87 * Searches for an element called NAME starting from POINTER. The
88 * name is composed by differents identifiers separated by dots. When
89 * *POINTER has a name, the first identifier must be the name of
90 * *POINTER, otherwise it must be the name of one child of *POINTER.
92 * Return value: the searching result. NULL if not found.
95 asn1_find_node (ASN1_TYPE pointer
, const char *name
)
98 char *n_end
, n
[MAX_NAME_SIZE
+ 1];
111 { /* has *pointer got a name ? */
112 n_end
= strchr (n_start
, '.'); /* search the first dot */
115 memcpy (n
, n_start
, n_end
- n_start
);
116 n
[n_end
- n_start
] = 0;
122 _asn1_str_cpy (n
, sizeof (n
), n_start
);
128 if ((p
->name
) && (!strcmp (p
->name
, n
)))
138 { /* *pointer doesn't have a name */
144 { /* Has the end of NAME been reached? */
145 n_end
= strchr (n_start
, '.'); /* search the next dot */
148 memcpy (n
, n_start
, n_end
- n_start
);
149 n
[n_end
- n_start
] = 0;
155 _asn1_str_cpy (n
, sizeof (n
), n_start
);
164 /* The identifier "?LAST" indicates the last element
165 in the right chain. */
166 if (!strcmp (n
, "?LAST"))
177 if ((p
->name
) && (!strcmp (p
->name
, n
)))
191 /******************************************************************/
192 /* Function : _asn1_set_value */
193 /* Description: sets the field VALUE in a NODE_ASN element. The */
194 /* previous value (if exist) will be lost */
196 /* node: element pointer. */
197 /* value: pointer to the value that you want to set. */
198 /* len: character number of value. */
199 /* Return: pointer to the NODE_ASN element. */
200 /******************************************************************/
202 _asn1_set_value (node_asn
* node
, const void *_value
, unsigned int len
)
204 const unsigned char *value
= _value
;
210 _asn1_free (node
->value
);
216 node
->value
= (unsigned char *) _asn1_malloc (len
);
217 if (node
->value
== NULL
)
219 node
->value_len
= len
;
221 memcpy (node
->value
, value
, len
);
225 /******************************************************************/
226 /* Function : _asn1_set_name */
227 /* Description: sets the field NAME in a NODE_ASN element. The */
228 /* previous value (if exist) will be lost */
230 /* node: element pointer. */
231 /* name: a null terminated string with the name that you want */
233 /* Return: pointer to the NODE_ASN element. */
234 /******************************************************************/
236 _asn1_set_name (node_asn
* node
, const char *name
)
243 _asn1_free (node
->name
);
252 node
->name
= (char *) _asn1_strdup (name
);
253 if (node
->name
== NULL
)
261 /******************************************************************/
262 /* Function : _asn1_set_right */
263 /* Description: sets the field RIGHT in a NODE_ASN element. */
265 /* node: element pointer. */
266 /* right: pointer to a NODE_ASN element that you want be pointed*/
268 /* Return: pointer to *NODE. */
269 /******************************************************************/
271 _asn1_set_right (node_asn
* node
, node_asn
* right
)
281 /******************************************************************/
282 /* Function : _asn1_get_right */
283 /* Description: returns the element pointed by the RIGHT field of */
284 /* a NODE_ASN element. */
286 /* node: NODE_ASN element pointer. */
287 /* Return: field RIGHT of NODE. */
288 /******************************************************************/
290 _asn1_get_right (node_asn
* node
)
297 /******************************************************************/
298 /* Function : _asn1_get_last_right */
299 /* Description: return the last element along the right chain. */
301 /* node: starting element pointer. */
302 /* Return: pointer to the last element along the right chain. */
303 /******************************************************************/
305 _asn1_get_last_right (node_asn
* node
)
317 /******************************************************************/
318 /* Function : _asn1_set_down */
319 /* Description: sets the field DOWN in a NODE_ASN element. */
321 /* node: element pointer. */
322 /* down: pointer to a NODE_ASN element that you want be pointed */
324 /* Return: pointer to *NODE. */
325 /******************************************************************/
327 _asn1_set_down (node_asn
* node
, node_asn
* down
)
337 /******************************************************************/
338 /* Function : _asn1_get_down */
339 /* Description: returns the element pointed by the DOWN field of */
340 /* a NODE_ASN element. */
342 /* node: NODE_ASN element pointer. */
343 /* Return: field DOWN of NODE. */
344 /******************************************************************/
346 _asn1_get_down (node_asn
* node
)
353 /******************************************************************/
354 /* Function : _asn1_get_name */
355 /* Description: returns the name of a NODE_ASN element. */
357 /* node: NODE_ASN element pointer. */
358 /* Return: a null terminated string. */
359 /******************************************************************/
361 _asn1_get_name (node_asn
* node
)
368 /******************************************************************/
369 /* Function : _asn1_mod_type */
370 /* Description: change the field TYPE of an NODE_ASN element. */
371 /* The new value is the old one | (bitwise or) the */
372 /* paramener VALUE. */
374 /* node: NODE_ASN element pointer. */
375 /* value: the integer value that must be or-ed with the current */
376 /* value of field TYPE. */
377 /* Return: NODE pointer. */
378 /******************************************************************/
380 _asn1_mod_type (node_asn
* node
, unsigned int value
)
389 /******************************************************************/
390 /* Function : _asn1_remove_node */
391 /* Description: gets free the memory allocated for an NODE_ASN */
392 /* element (not the elements pointed by it). */
394 /* node: NODE_ASN element pointer. */
395 /******************************************************************/
397 _asn1_remove_node (node_asn
* node
)
402 if (node
->name
!= NULL
)
403 _asn1_free (node
->name
);
404 if (node
->value
!= NULL
)
405 _asn1_free (node
->value
);
409 /******************************************************************/
410 /* Function : _asn1_find_up */
411 /* Description: return the father of the NODE_ASN element. */
413 /* node: NODE_ASN element pointer. */
414 /* Return: Null if not found. */
415 /******************************************************************/
417 _asn1_find_up (node_asn
* node
)
426 while ((p
->left
!= NULL
) && (p
->left
->right
== p
))
432 /******************************************************************/
433 /* Function : _asn1_delete_list */
434 /* Description: deletes the list elements (not the elements */
435 /* pointed by them). */
436 /******************************************************************/
438 _asn1_delete_list (void)
440 list_type
*listElement
;
444 listElement
= firstElement
;
445 firstElement
= firstElement
->next
;
446 _asn1_free (listElement
);
450 /******************************************************************/
451 /* Function : _asn1_delete_list_and nodes */
452 /* Description: deletes the list elements and the elements */
453 /* pointed by them. */
454 /******************************************************************/
456 _asn1_delete_list_and_nodes (void)
458 list_type
*listElement
;
462 listElement
= firstElement
;
463 firstElement
= firstElement
->next
;
464 _asn1_remove_node (listElement
->node
);
465 _asn1_free (listElement
);
471 _asn1_ltostr (long v
, char *str
)
491 temp
[start
+ count
] = '0' + (char) r
;
497 for (k
= 0; k
< count
; k
++)
498 str
[k
+ start
] = temp
[start
+ count
- k
- 1];
499 str
[count
+ start
] = 0;
504 /******************************************************************/
505 /* Function : _asn1_change_integer_value */
506 /* Description: converts into DER coding the value assign to an */
507 /* INTEGER constant. */
509 /* node: root of an ASN1element. */
511 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
512 /* otherwise ASN1_SUCCESS */
513 /******************************************************************/
515 _asn1_change_integer_value (ASN1_TYPE node
)
518 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
519 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+ 1];
523 return ASN1_ELEMENT_NOT_FOUND
;
528 if ((type_field (p
->type
) == TYPE_INTEGER
) && (p
->type
& CONST_ASSIGN
))
532 _asn1_convert_integer (p
->value
, val
, sizeof (val
), &len
);
533 asn1_octet_der (val
, len
, val2
, &len
);
534 _asn1_set_value (p
, val2
, len
);
552 p
= _asn1_find_up (p
);
572 /******************************************************************/
573 /* Function : _asn1_expand_object_id */
574 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
576 /* node: root of an ASN1 element. */
578 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
579 /* otherwise ASN1_SUCCESS */
580 /******************************************************************/
582 _asn1_expand_object_id (ASN1_TYPE node
)
584 node_asn
*p
, *p2
, *p3
, *p4
, *p5
;
585 char name_root
[MAX_NAME_SIZE
], name2
[2 * MAX_NAME_SIZE
+ 1];
589 return ASN1_ELEMENT_NOT_FOUND
;
591 _asn1_str_cpy (name_root
, sizeof (name_root
), node
->name
);
596 while (!((p
== node
) && (move
== UP
)))
600 if ((type_field (p
->type
) == TYPE_OBJECT_ID
)
601 && (p
->type
& CONST_ASSIGN
))
604 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
606 if (p2
->value
&& !isdigit (p2
->value
[0]))
608 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
609 _asn1_str_cat (name2
, sizeof (name2
), ".");
610 _asn1_str_cat (name2
, sizeof (name2
), p2
->value
);
611 p3
= asn1_find_node (node
, name2
);
612 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
613 !(p3
->type
& CONST_ASSIGN
))
614 return ASN1_ELEMENT_NOT_FOUND
;
615 _asn1_set_down (p
, p2
->right
);
616 _asn1_remove_node (p2
);
621 if (type_field (p4
->type
) == TYPE_CONSTANT
)
623 p5
= _asn1_add_node_only (TYPE_CONSTANT
);
624 _asn1_set_name (p5
, p4
->name
);
625 tlen
= strlen (p4
->value
);
627 _asn1_set_value (p5
, p4
->value
, tlen
+ 1);
630 _asn1_set_right (p5
, p
->down
);
631 _asn1_set_down (p
, p5
);
635 _asn1_set_right (p5
, p2
->right
);
636 _asn1_set_right (p2
, p5
);
674 p
= _asn1_find_up (p
);
678 /*******************************/
680 /*******************************/
684 while (!((p
== node
) && (move
== UP
)))
688 if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
689 (p
->type
& CONST_DEFAULT
))
692 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
694 _asn1_str_cpy (name2
, sizeof (name2
), name_root
);
695 _asn1_str_cat (name2
, sizeof (name2
), ".");
696 _asn1_str_cat (name2
, sizeof (name2
), p2
->value
);
697 p3
= asn1_find_node (node
, name2
);
698 if (!p3
|| (type_field (p3
->type
) != TYPE_OBJECT_ID
) ||
699 !(p3
->type
& CONST_ASSIGN
))
700 return ASN1_ELEMENT_NOT_FOUND
;
705 if (type_field (p4
->type
) == TYPE_CONSTANT
)
708 _asn1_str_cat (name2
, sizeof (name2
), ".");
709 _asn1_str_cat (name2
, sizeof (name2
), p4
->value
);
713 tlen
= strlen (name2
);
715 _asn1_set_value (p2
, name2
, tlen
+ 1);
745 p
= _asn1_find_up (p
);
752 /******************************************************************/
753 /* Function : _asn1_type_set_config */
754 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
755 /* in the fields of the SET elements. */
757 /* node: root of an ASN1 element. */
759 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
760 /* otherwise ASN1_SUCCESS */
761 /******************************************************************/
763 _asn1_type_set_config (ASN1_TYPE node
)
769 return ASN1_ELEMENT_NOT_FOUND
;
774 while (!((p
== node
) && (move
== UP
)))
778 if (type_field (p
->type
) == TYPE_SET
)
783 if (type_field (p2
->type
) != TYPE_TAG
)
784 p2
->type
|= CONST_SET
| CONST_NOT_USED
;
815 p
= _asn1_find_up (p
);
822 /******************************************************************/
823 /* Function : _asn1_check_identifier */
824 /* Description: checks the definitions of all the identifiers */
825 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
826 /* The _asn1_identifierMissing global variable is filled if */
829 /* node: root of an ASN1 element. */
831 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
832 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
833 /* otherwise ASN1_SUCCESS */
834 /******************************************************************/
836 _asn1_check_identifier (ASN1_TYPE node
)
839 char name2
[MAX_NAME_SIZE
* 2 + 2];
842 return ASN1_ELEMENT_NOT_FOUND
;
847 if (type_field (p
->type
) == TYPE_IDENTIFIER
)
849 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
850 _asn1_str_cat (name2
, sizeof (name2
), ".");
851 _asn1_str_cat (name2
, sizeof (name2
), p
->value
);
852 p2
= asn1_find_node (node
, name2
);
855 strcpy (_asn1_identifierMissing
, p
->value
);
856 return ASN1_IDENTIFIER_NOT_FOUND
;
859 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
860 (p
->type
& CONST_DEFAULT
))
863 if (p2
&& (type_field (p2
->type
) == TYPE_DEFAULT
))
865 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
866 _asn1_str_cat (name2
, sizeof (name2
), ".");
867 _asn1_str_cat (name2
, sizeof (name2
), p2
->value
);
868 strcpy (_asn1_identifierMissing
, p2
->value
);
869 p2
= asn1_find_node (node
, name2
);
870 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
871 !(p2
->type
& CONST_ASSIGN
))
872 return ASN1_IDENTIFIER_NOT_FOUND
;
874 _asn1_identifierMissing
[0] = 0;
877 else if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
878 (p
->type
& CONST_ASSIGN
))
881 if (p2
&& (type_field (p2
->type
) == TYPE_CONSTANT
))
883 if (p2
->value
&& !isdigit (p2
->value
[0]))
885 _asn1_str_cpy (name2
, sizeof (name2
), node
->name
);
886 _asn1_str_cat (name2
, sizeof (name2
), ".");
887 _asn1_str_cat (name2
, sizeof (name2
), p2
->value
);
888 strcpy (_asn1_identifierMissing
, p2
->value
);
889 p2
= asn1_find_node (node
, name2
);
890 if (!p2
|| (type_field (p2
->type
) != TYPE_OBJECT_ID
) ||
891 !(p2
->type
& CONST_ASSIGN
))
892 return ASN1_IDENTIFIER_NOT_FOUND
;
894 _asn1_identifierMissing
[0] = 0;
909 p
= _asn1_find_up (p
);
928 /******************************************************************/
929 /* Function : _asn1_set_default_tag */
930 /* Description: sets the default IMPLICIT or EXPLICIT property in */
931 /* the tagged elements that don't have this declaration. */
933 /* node: pointer to a DEFINITIONS element. */
935 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
936 /* a DEFINITIONS element, */
937 /* otherwise ASN1_SUCCESS */
938 /******************************************************************/
940 _asn1_set_default_tag (ASN1_TYPE node
)
944 if ((node
== NULL
) || (type_field (node
->type
) != TYPE_DEFINITIONS
))
945 return ASN1_ELEMENT_NOT_FOUND
;
950 if ((type_field (p
->type
) == TYPE_TAG
) &&
951 !(p
->type
& CONST_EXPLICIT
) && !(p
->type
& CONST_IMPLICIT
))
953 if (node
->type
& CONST_EXPLICIT
)
954 p
->type
|= CONST_EXPLICIT
;
956 p
->type
|= CONST_IMPLICIT
;
969 p
= _asn1_find_up (p
);
990 parse_version_number (const char *s
, int *number
)
994 if (*s
== '0' && isdigit (s
[1]))
995 return NULL
; /* leading zeros are not allowed */
996 for (; isdigit (*s
); s
++)
1002 return val
< 0 ? NULL
: s
;
1005 /* The parse version functions were copied from libgcrypt.
1008 parse_version_string (const char *s
, int *major
, int *minor
, int *micro
)
1010 s
= parse_version_number (s
, major
);
1011 if (!s
|| *s
!= '.')
1014 s
= parse_version_number (s
, minor
);
1015 if (!s
|| *s
!= '.')
1018 s
= parse_version_number (s
, micro
);
1021 return s
; /* patchlevel */
1025 * asn1_check_version - check for library version
1026 * @req_version: Required version number, or NULL.
1028 * Check that the the version of the library is at minimum the
1029 * requested one and return the version string; return %NULL if the
1030 * condition is not satisfied. If a %NULL is passed to this function,
1031 * no check is done, but the version string is simply returned.
1033 * See %LIBTASN1_VERSION for a suitable @req_version string.
1035 * Return value: Version string of run-time library, or %NULL if the
1036 * run-time library does not meet the required version number.
1039 asn1_check_version (const char *req_version
)
1041 const char *ver
= LIBTASN1_VERSION
;
1042 int my_major
, my_minor
, my_micro
;
1043 int rq_major
, rq_minor
, rq_micro
;
1044 const char *my_plvl
, *rq_plvl
;
1049 my_plvl
= parse_version_string (ver
, &my_major
, &my_minor
, &my_micro
);
1051 return NULL
; /* very strange our own version is bogus */
1052 rq_plvl
= parse_version_string (req_version
, &rq_major
, &rq_minor
,
1055 return NULL
; /* req version string is invalid */
1057 if (my_major
> rq_major
1058 || (my_major
== rq_major
&& my_minor
> rq_minor
)
1059 || (my_major
== rq_major
&& my_minor
== rq_minor
1060 && my_micro
> rq_micro
)
1061 || (my_major
== rq_major
&& my_minor
== rq_minor
1062 && my_micro
== rq_micro
&& strcmp (my_plvl
, rq_plvl
) >= 0))