2 * Copyright (C) 2000, 2001, 2004, 2006, 2007, 2008, 2009, 2010 Free
3 * Software Foundation, Inc.
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
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_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 TYPE_ */
52 /* and CONST_ constants). */
53 /* Return: pointer to the new element. */
54 /******************************************************/
56 _asn1_add_node (unsigned int type)
58 list_type *listElement;
61 punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
65 listElement = (list_type *) _asn1_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_TYPE pointer, const char *name)
97 char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
110 { /* has *pointer got a name ? */
111 n_end = strchr (n_start, '.'); /* search the first dot */
114 memcpy (n, n_start, n_end - n_start);
115 n[n_end - n_start] = 0;
121 _asn1_str_cpy (n, sizeof (n), n_start);
127 if ((p->name) && (!strcmp (p->name, n)))
137 { /* *pointer doesn't have a name */
143 { /* Has the end of NAME been reached? */
144 n_end = strchr (n_start, '.'); /* search the next dot */
147 memcpy (n, n_start, n_end - n_start);
148 n[n_end - n_start] = 0;
154 _asn1_str_cpy (n, sizeof (n), n_start);
163 /* The identifier "?LAST" indicates the last element
164 in the right chain. */
165 if (!strcmp (n, "?LAST"))
176 if ((p->name) && (!strcmp (p->name, n)))
190 /******************************************************************/
191 /* Function : _asn1_set_value */
192 /* Description: sets the field VALUE in a NODE_ASN element. The */
193 /* previous value (if exist) will be lost */
195 /* node: element pointer. */
196 /* value: pointer to the value that you want to set. */
197 /* len: character number of value. */
198 /* Return: pointer to the NODE_ASN element. */
199 /******************************************************************/
201 _asn1_set_value (ASN1_TYPE node, const void *value, unsigned int len)
207 if (node->value != node->small_value)
208 _asn1_free (node->value);
216 if (len < sizeof (node->small_value))
218 node->value = node->small_value;
222 node->value = _asn1_malloc (len);
223 if (node->value == NULL)
226 node->value_len = len;
228 memcpy (node->value, value, len);
232 /******************************************************************/
233 /* Function : _asn1_set_value_octet */
234 /* Description: sets the field VALUE in a NODE_ASN element. The */
235 /* previous value (if exist) will be lost. The value */
236 /* given is stored as an octet string. */
238 /* node: element pointer. */
239 /* value: pointer to the value that you want to set. */
240 /* len: character number of value. */
241 /* Return: pointer to the NODE_ASN element. */
242 /******************************************************************/
244 _asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len)
252 asn1_length_der (len, NULL, &len2);
253 temp = (unsigned char *) _asn1_malloc (len + len2);
257 asn1_octet_der (value, len, temp, &len2);
258 return _asn1_set_value_m (node, temp, len2);
261 /* the same as _asn1_set_value except that it sets an already malloc'ed
265 _asn1_set_value_m (ASN1_TYPE node, void *value, unsigned int len)
272 if (node->value != node->small_value)
273 _asn1_free (node->value);
282 node->value_len = len;
287 /******************************************************************/
288 /* Function : _asn1_append_value */
289 /* Description: appends to the field VALUE in a NODE_ASN element. */
292 /* node: element pointer. */
293 /* value: pointer to the value that you want to be appended. */
294 /* len: character number of value. */
295 /* Return: pointer to the NODE_ASN element. */
296 /******************************************************************/
298 _asn1_append_value (ASN1_TYPE node, const void *value, unsigned int len)
302 if (node->value != NULL && node->value != node->small_value)
304 /* value is allocated */
305 int prev_len = node->value_len;
306 node->value_len += len;
307 node->value = _asn1_realloc (node->value, node->value_len);
308 if (node->value == NULL)
313 memcpy (&node->value[prev_len], value, len);
317 else if (node->value == node->small_value)
319 /* value is in node */
320 int prev_len = node->value_len;
321 node->value_len += len;
322 node->value = _asn1_malloc (node->value_len);
323 if (node->value == NULL)
328 memcpy (node->value, node->small_value, prev_len);
329 memcpy (&node->value[prev_len], value, len);
333 else /* node->value == NULL */
334 return _asn1_set_value (node, value, len);
337 /******************************************************************/
338 /* Function : _asn1_set_name */
339 /* Description: sets the field NAME in a NODE_ASN element. The */
340 /* previous value (if exist) will be lost */
342 /* node: element pointer. */
343 /* name: a null terminated string with the name that you want */
345 /* Return: pointer to the NODE_ASN element. */
346 /******************************************************************/
348 _asn1_set_name (ASN1_TYPE node, const char *name)
355 _asn1_free (node->name);
364 node->name = (char *) _asn1_strdup (name);
365 if (node->name == NULL)
373 /******************************************************************/
374 /* Function : _asn1_set_right */
375 /* Description: sets the field RIGHT in a NODE_ASN element. */
377 /* node: element pointer. */
378 /* right: pointer to a NODE_ASN element that you want be pointed*/
380 /* Return: pointer to *NODE. */
381 /******************************************************************/
383 _asn1_set_right (ASN1_TYPE node, ASN1_TYPE right)
393 /******************************************************************/
394 /* Function : _asn1_get_right */
395 /* Description: returns the element pointed by the RIGHT field of */
396 /* a NODE_ASN element. */
398 /* node: NODE_ASN element pointer. */
399 /* Return: field RIGHT of NODE. */
400 /******************************************************************/
402 _asn1_get_right (ASN1_TYPE node)
409 /******************************************************************/
410 /* Function : _asn1_get_last_right */
411 /* Description: return the last element along the right chain. */
413 /* node: starting element pointer. */
414 /* Return: pointer to the last element along the right chain. */
415 /******************************************************************/
417 _asn1_get_last_right (ASN1_TYPE node)
429 /******************************************************************/
430 /* Function : _asn1_set_down */
431 /* Description: sets the field DOWN in a NODE_ASN element. */
433 /* node: element pointer. */
434 /* down: pointer to a NODE_ASN element that you want be pointed */
436 /* Return: pointer to *NODE. */
437 /******************************************************************/
439 _asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
449 /******************************************************************/
450 /* Function : _asn1_get_down */
451 /* Description: returns the element pointed by the DOWN field of */
452 /* a NODE_ASN element. */
454 /* node: NODE_ASN element pointer. */
455 /* Return: field DOWN of NODE. */
456 /******************************************************************/
458 _asn1_get_down (ASN1_TYPE node)
465 /******************************************************************/
466 /* Function : _asn1_get_name */
467 /* Description: returns the name of a NODE_ASN element. */
469 /* node: NODE_ASN element pointer. */
470 /* Return: a null terminated string. */
471 /******************************************************************/
473 _asn1_get_name (ASN1_TYPE node)
480 /******************************************************************/
481 /* Function : _asn1_mod_type */
482 /* Description: change the field TYPE of an NODE_ASN element. */
483 /* The new value is the old one | (bitwise or) the */
484 /* paramener VALUE. */
486 /* node: NODE_ASN element pointer. */
487 /* value: the integer value that must be or-ed with the current */
488 /* value of field TYPE. */
489 /* Return: NODE pointer. */
490 /******************************************************************/
492 _asn1_mod_type (ASN1_TYPE node, unsigned int value)
501 /******************************************************************/
502 /* Function : _asn1_remove_node */
503 /* Description: gets free the memory allocated for an NODE_ASN */
504 /* element (not the elements pointed by it). */
506 /* node: NODE_ASN element pointer. */
507 /******************************************************************/
509 _asn1_remove_node (ASN1_TYPE node)
514 if (node->name != NULL)
515 _asn1_free (node->name);
516 if (node->value != NULL && node->value != node->small_value)
517 _asn1_free (node->value);
521 /******************************************************************/
522 /* Function : _asn1_find_up */
523 /* Description: return the father of the NODE_ASN element. */
525 /* node: NODE_ASN element pointer. */
526 /* Return: Null if not found. */
527 /******************************************************************/
529 _asn1_find_up (ASN1_TYPE node)
538 while ((p->left != NULL) && (p->left->right == p))
544 /******************************************************************/
545 /* Function : _asn1_delete_list */
546 /* Description: deletes the list elements (not the elements */
547 /* pointed by them). */
548 /******************************************************************/
550 _asn1_delete_list (void)
552 list_type *listElement;
556 listElement = firstElement;
557 firstElement = firstElement->next;
558 _asn1_free (listElement);
562 /******************************************************************/
563 /* Function : _asn1_delete_list_and nodes */
564 /* Description: deletes the list elements and the elements */
565 /* pointed by them. */
566 /******************************************************************/
568 _asn1_delete_list_and_nodes (void)
570 list_type *listElement;
574 listElement = firstElement;
575 firstElement = firstElement->next;
576 _asn1_remove_node (listElement->node);
577 _asn1_free (listElement);
583 _asn1_ltostr (long v, char *str)
603 temp[start + count] = '0' + (char) r;
609 for (k = 0; k < count; k++)
610 str[k + start] = temp[start + count - k - 1];
611 str[count + start] = 0;
616 /******************************************************************/
617 /* Function : _asn1_change_integer_value */
618 /* Description: converts into DER coding the value assign to an */
619 /* INTEGER constant. */
621 /* node: root of an ASN1element. */
623 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
624 /* otherwise ASN1_SUCCESS */
625 /******************************************************************/
627 _asn1_change_integer_value (ASN1_TYPE node)
630 unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
631 unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
635 return ASN1_ELEMENT_NOT_FOUND;
640 if ((type_field (p->type) == TYPE_INTEGER) && (p->type & CONST_ASSIGN))
644 _asn1_convert_integer (p->value, val, sizeof (val), &len);
645 asn1_octet_der (val, len, val2, &len);
646 _asn1_set_value (p, val2, len);
664 p = _asn1_find_up (p);
684 /******************************************************************/
685 /* Function : _asn1_expand_object_id */
686 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
688 /* node: root of an ASN1 element. */
690 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
691 /* otherwise ASN1_SUCCESS */
692 /******************************************************************/
694 _asn1_expand_object_id (ASN1_TYPE node)
696 ASN1_TYPE p, p2, p3, p4, p5;
697 char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
701 return ASN1_ELEMENT_NOT_FOUND;
703 _asn1_str_cpy (name_root, sizeof (name_root), node->name);
708 while (!((p == node) && (move == UP)))
712 if ((type_field (p->type) == TYPE_OBJECT_ID)
713 && (p->type & CONST_ASSIGN))
716 if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
718 if (p2->value && !isdigit (p2->value[0]))
720 _asn1_str_cpy (name2, sizeof (name2), name_root);
721 _asn1_str_cat (name2, sizeof (name2), ".");
722 _asn1_str_cat (name2, sizeof (name2), p2->value);
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 = 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), 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), p4->value);
825 tlen = strlen (name2);
827 _asn1_set_value (p2, name2, tlen + 1);
857 p = _asn1_find_up (p);
864 /******************************************************************/
865 /* Function : _asn1_type_set_config */
866 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
867 /* in the fields of the SET elements. */
869 /* node: root of an ASN1 element. */
871 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
872 /* otherwise ASN1_SUCCESS */
873 /******************************************************************/
875 _asn1_type_set_config (ASN1_TYPE node)
881 return ASN1_ELEMENT_NOT_FOUND;
886 while (!((p == node) && (move == UP)))
890 if (type_field (p->type) == TYPE_SET)
895 if (type_field (p2->type) != TYPE_TAG)
896 p2->type |= CONST_SET | CONST_NOT_USED;
927 p = _asn1_find_up (p);
934 /******************************************************************/
935 /* Function : _asn1_check_identifier */
936 /* Description: checks the definitions of all the identifiers */
937 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
938 /* The _asn1_identifierMissing global variable is filled if */
941 /* node: root of an ASN1 element. */
943 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
944 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
945 /* otherwise ASN1_SUCCESS */
946 /******************************************************************/
948 _asn1_check_identifier (ASN1_TYPE node)
951 char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
954 return ASN1_ELEMENT_NOT_FOUND;
959 if (type_field (p->type) == TYPE_IDENTIFIER)
961 _asn1_str_cpy (name2, sizeof (name2), node->name);
962 _asn1_str_cat (name2, sizeof (name2), ".");
963 _asn1_str_cat (name2, sizeof (name2), p->value);
964 p2 = asn1_find_node (node, name2);
967 strcpy (_asn1_identifierMissing, p->value);
968 return ASN1_IDENTIFIER_NOT_FOUND;
971 else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
972 (p->type & CONST_DEFAULT))
975 if (p2 && (type_field (p2->type) == TYPE_DEFAULT))
977 _asn1_str_cpy (name2, sizeof (name2), node->name);
978 _asn1_str_cat (name2, sizeof (name2), ".");
979 _asn1_str_cat (name2, sizeof (name2), p2->value);
980 strcpy (_asn1_identifierMissing, p2->value);
981 p2 = asn1_find_node (node, name2);
982 if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
983 !(p2->type & CONST_ASSIGN))
984 return ASN1_IDENTIFIER_NOT_FOUND;
986 _asn1_identifierMissing[0] = 0;
989 else if ((type_field (p->type) == TYPE_OBJECT_ID) &&
990 (p->type & CONST_ASSIGN))
993 if (p2 && (type_field (p2->type) == TYPE_CONSTANT))
995 if (p2->value && !isdigit (p2->value[0]))
997 _asn1_str_cpy (name2, sizeof (name2), node->name);
998 _asn1_str_cat (name2, sizeof (name2), ".");
999 _asn1_str_cat (name2, sizeof (name2), p2->value);
1000 strcpy (_asn1_identifierMissing, p2->value);
1001 p2 = asn1_find_node (node, name2);
1002 if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
1003 !(p2->type & CONST_ASSIGN))
1004 return ASN1_IDENTIFIER_NOT_FOUND;
1006 _asn1_identifierMissing[0] = 0;
1021 p = _asn1_find_up (p);
1036 return ASN1_SUCCESS;
1040 /******************************************************************/
1041 /* Function : _asn1_set_default_tag */
1042 /* Description: sets the default IMPLICIT or EXPLICIT property in */
1043 /* the tagged elements that don't have this declaration. */
1045 /* node: pointer to a DEFINITIONS element. */
1047 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
1048 /* a DEFINITIONS element, */
1049 /* otherwise ASN1_SUCCESS */
1050 /******************************************************************/
1052 _asn1_set_default_tag (ASN1_TYPE node)
1056 if ((node == NULL) || (type_field (node->type) != TYPE_DEFINITIONS))
1057 return ASN1_ELEMENT_NOT_FOUND;
1062 if ((type_field (p->type) == TYPE_TAG) &&
1063 !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1065 if (node->type & CONST_EXPLICIT)
1066 p->type |= CONST_EXPLICIT;
1068 p->type |= CONST_IMPLICIT;
1081 p = _asn1_find_up (p);
1096 return ASN1_SUCCESS;