2 * Copyright (C) 2000-2014 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 (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 /* flags: ASN1_DELETE_FLAG_* */
454 /******************************************************************/
456 _asn1_remove_node (asn1_node node, unsigned int flags)
461 if (node->value != NULL)
463 if (flags & ASN1_DELETE_FLAG_ZEROIZE)
465 safe_memset(node->value, 0, node->value_len);
468 if (node->value != node->small_value)
474 /******************************************************************/
475 /* Function : _asn1_find_up */
476 /* Description: return the father of the NODE_ASN element. */
478 /* node: NODE_ASN element pointer. */
479 /* Return: Null if not found. */
480 /******************************************************************/
482 _asn1_find_up (asn1_node node)
491 while ((p->left != NULL) && (p->left->right == p))
497 /******************************************************************/
498 /* Function : _asn1_delete_list */
499 /* Description: deletes the list elements (not the elements */
500 /* pointed by them). */
501 /******************************************************************/
503 _asn1_delete_list (void)
505 list_type *listElement;
509 listElement = firstElement;
510 firstElement = firstElement->next;
515 /******************************************************************/
516 /* Function : _asn1_delete_list_and nodes */
517 /* Description: deletes the list elements and the elements */
518 /* pointed by them. */
519 /******************************************************************/
521 _asn1_delete_list_and_nodes (void)
523 list_type *listElement;
527 listElement = firstElement;
528 firstElement = firstElement->next;
529 _asn1_remove_node (listElement->node, 0);
536 _asn1_ltostr (long v, char *str)
539 char temp[LTOSTR_MAX_SIZE];
556 temp[start + count] = '0' + (char) r;
562 for (k = 0; k < count; k++)
563 str[k + start] = temp[start + count - k - 1];
564 str[count + start] = 0;
569 /******************************************************************/
570 /* Function : _asn1_change_integer_value */
571 /* Description: converts into DER coding the value assign to an */
572 /* INTEGER constant. */
574 /* node: root of an ASN1element. */
576 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
577 /* otherwise ASN1_SUCCESS */
578 /******************************************************************/
580 _asn1_change_integer_value (asn1_node node)
583 unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
584 unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
588 return ASN1_ELEMENT_NOT_FOUND;
593 if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
594 && (p->type & CONST_ASSIGN))
598 _asn1_convert_integer (p->value, val, sizeof (val), &len);
599 asn1_octet_der (val, len, val2, &len);
600 _asn1_set_value (p, val2, len);
618 p = _asn1_find_up (p);
638 /******************************************************************/
639 /* Function : _asn1_expand_object_id */
640 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
642 /* node: root of an ASN1 element. */
644 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
645 /* otherwise ASN1_SUCCESS */
646 /******************************************************************/
648 _asn1_expand_object_id (asn1_node node)
650 asn1_node p, p2, p3, p4, p5;
651 char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
655 return ASN1_ELEMENT_NOT_FOUND;
657 _asn1_str_cpy (name_root, sizeof (name_root), node->name);
662 while (!((p == node) && (move == UP)))
666 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
667 && (p->type & CONST_ASSIGN))
670 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
672 if (p2->value && !isdigit (p2->value[0]))
674 _asn1_str_cpy (name2, sizeof (name2), name_root);
675 _asn1_str_cat (name2, sizeof (name2), ".");
676 _asn1_str_cat (name2, sizeof (name2),
678 p3 = asn1_find_node (node, name2);
680 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
681 || !(p3->type & CONST_ASSIGN))
682 return ASN1_ELEMENT_NOT_FOUND;
683 _asn1_set_down (p, p2->right);
684 _asn1_remove_node (p2, 0);
689 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
692 _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
693 _asn1_set_name (p5, p4->name);
694 tlen = _asn1_strlen (p4->value);
696 _asn1_set_value (p5, p4->value, tlen + 1);
699 _asn1_set_right (p5, p->down);
700 _asn1_set_down (p, p5);
704 _asn1_set_right (p5, p2->right);
705 _asn1_set_right (p2, p5);
743 p = _asn1_find_up (p);
747 /*******************************/
749 /*******************************/
753 while (!((p == node) && (move == UP)))
757 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
758 (p->type & CONST_DEFAULT))
761 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
763 _asn1_str_cpy (name2, sizeof (name2), name_root);
764 _asn1_str_cat (name2, sizeof (name2), ".");
765 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
766 p3 = asn1_find_node (node, name2);
767 if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
768 || !(p3->type & CONST_ASSIGN))
769 return ASN1_ELEMENT_NOT_FOUND;
774 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
777 _asn1_str_cat (name2, sizeof (name2), ".");
778 _asn1_str_cat (name2, sizeof (name2),
783 tlen = strlen (name2);
785 _asn1_set_value (p2, name2, tlen + 1);
815 p = _asn1_find_up (p);
822 /******************************************************************/
823 /* Function : _asn1_type_set_config */
824 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
825 /* in the fields of the SET elements. */
827 /* node: root of an ASN1 element. */
829 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
830 /* otherwise ASN1_SUCCESS */
831 /******************************************************************/
833 _asn1_type_set_config (asn1_node node)
839 return ASN1_ELEMENT_NOT_FOUND;
844 while (!((p == node) && (move == UP)))
848 if (type_field (p->type) == ASN1_ETYPE_SET)
853 if (type_field (p2->type) != ASN1_ETYPE_TAG)
854 p2->type |= CONST_SET | CONST_NOT_USED;
885 p = _asn1_find_up (p);
892 /******************************************************************/
893 /* Function : _asn1_check_identifier */
894 /* Description: checks the definitions of all the identifiers */
895 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
896 /* The _asn1_identifierMissing global variable is filled if */
899 /* node: root of an ASN1 element. */
901 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
902 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
903 /* otherwise ASN1_SUCCESS */
904 /******************************************************************/
906 _asn1_check_identifier (asn1_node node)
909 char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
912 return ASN1_ELEMENT_NOT_FOUND;
917 if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
919 _asn1_str_cpy (name2, sizeof (name2), node->name);
920 _asn1_str_cat (name2, sizeof (name2), ".");
921 _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
922 p2 = asn1_find_node (node, name2);
926 _asn1_strcpy (_asn1_identifierMissing, p->value);
928 _asn1_strcpy (_asn1_identifierMissing, "(null)");
929 return ASN1_IDENTIFIER_NOT_FOUND;
932 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
933 (p->type & CONST_DEFAULT))
936 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
938 _asn1_str_cpy (name2, sizeof (name2), node->name);
939 _asn1_str_cat (name2, sizeof (name2), ".");
940 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
941 _asn1_strcpy (_asn1_identifierMissing, p2->value);
942 p2 = asn1_find_node (node, name2);
943 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
944 !(p2->type & CONST_ASSIGN))
945 return ASN1_IDENTIFIER_NOT_FOUND;
947 _asn1_identifierMissing[0] = 0;
950 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
951 (p->type & CONST_ASSIGN))
954 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
956 if (p2->value && !isdigit (p2->value[0]))
958 _asn1_str_cpy (name2, sizeof (name2), node->name);
959 _asn1_str_cat (name2, sizeof (name2), ".");
960 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
961 _asn1_strcpy (_asn1_identifierMissing, p2->value);
962 p2 = asn1_find_node (node, name2);
963 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
964 || !(p2->type & CONST_ASSIGN))
965 return ASN1_IDENTIFIER_NOT_FOUND;
967 _asn1_identifierMissing[0] = 0;
982 p = _asn1_find_up (p);
1001 /******************************************************************/
1002 /* Function : _asn1_set_default_tag */
1003 /* Description: sets the default IMPLICIT or EXPLICIT property in */
1004 /* the tagged elements that don't have this declaration. */
1006 /* node: pointer to a DEFINITIONS element. */
1008 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
1009 /* a DEFINITIONS element, */
1010 /* otherwise ASN1_SUCCESS */
1011 /******************************************************************/
1013 _asn1_set_default_tag (asn1_node node)
1017 if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
1018 return ASN1_ELEMENT_NOT_FOUND;
1023 if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
1024 !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1026 if (node->type & CONST_EXPLICIT)
1027 p->type |= CONST_EXPLICIT;
1029 p->type |= CONST_IMPLICIT;
1042 p = _asn1_find_up (p);
1057 return ASN1_SUCCESS;