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 (flags & ASN1_DELETE_FLAG_ZEROIZE)
462 memset(node->value, 0, node->value_len);
464 if (node->value != NULL && node->value != node->small_value)
469 /******************************************************************/
470 /* Function : _asn1_find_up */
471 /* Description: return the father of the NODE_ASN element. */
473 /* node: NODE_ASN element pointer. */
474 /* Return: Null if not found. */
475 /******************************************************************/
477 _asn1_find_up (asn1_node node)
486 while ((p->left != NULL) && (p->left->right == p))
492 /******************************************************************/
493 /* Function : _asn1_delete_list */
494 /* Description: deletes the list elements (not the elements */
495 /* pointed by them). */
496 /******************************************************************/
498 _asn1_delete_list (void)
500 list_type *listElement;
504 listElement = firstElement;
505 firstElement = firstElement->next;
510 /******************************************************************/
511 /* Function : _asn1_delete_list_and nodes */
512 /* Description: deletes the list elements and the elements */
513 /* pointed by them. */
514 /******************************************************************/
516 _asn1_delete_list_and_nodes (void)
518 list_type *listElement;
522 listElement = firstElement;
523 firstElement = firstElement->next;
524 _asn1_remove_node (listElement->node, 0);
531 _asn1_ltostr (long v, char *str)
551 temp[start + count] = '0' + (char) r;
557 for (k = 0; k < count; k++)
558 str[k + start] = temp[start + count - k - 1];
559 str[count + start] = 0;
564 /******************************************************************/
565 /* Function : _asn1_change_integer_value */
566 /* Description: converts into DER coding the value assign to an */
567 /* INTEGER constant. */
569 /* node: root of an ASN1element. */
571 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
572 /* otherwise ASN1_SUCCESS */
573 /******************************************************************/
575 _asn1_change_integer_value (asn1_node node)
578 unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
579 unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
583 return ASN1_ELEMENT_NOT_FOUND;
588 if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
589 && (p->type & CONST_ASSIGN))
593 _asn1_convert_integer (p->value, val, sizeof (val), &len);
594 asn1_octet_der (val, len, val2, &len);
595 _asn1_set_value (p, val2, len);
613 p = _asn1_find_up (p);
633 /******************************************************************/
634 /* Function : _asn1_expand_object_id */
635 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
637 /* node: root of an ASN1 element. */
639 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
640 /* otherwise ASN1_SUCCESS */
641 /******************************************************************/
643 _asn1_expand_object_id (asn1_node node)
645 asn1_node p, p2, p3, p4, p5;
646 char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
650 return ASN1_ELEMENT_NOT_FOUND;
652 _asn1_str_cpy (name_root, sizeof (name_root), node->name);
657 while (!((p == node) && (move == UP)))
661 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
662 && (p->type & CONST_ASSIGN))
665 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
667 if (p2->value && !isdigit (p2->value[0]))
669 _asn1_str_cpy (name2, sizeof (name2), name_root);
670 _asn1_str_cat (name2, sizeof (name2), ".");
671 _asn1_str_cat (name2, sizeof (name2),
673 p3 = asn1_find_node (node, name2);
675 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
676 || !(p3->type & CONST_ASSIGN))
677 return ASN1_ELEMENT_NOT_FOUND;
678 _asn1_set_down (p, p2->right);
679 _asn1_remove_node (p2, 0);
684 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
687 _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
688 _asn1_set_name (p5, p4->name);
689 tlen = _asn1_strlen (p4->value);
691 _asn1_set_value (p5, p4->value, tlen + 1);
694 _asn1_set_right (p5, p->down);
695 _asn1_set_down (p, p5);
699 _asn1_set_right (p5, p2->right);
700 _asn1_set_right (p2, p5);
738 p = _asn1_find_up (p);
742 /*******************************/
744 /*******************************/
748 while (!((p == node) && (move == UP)))
752 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
753 (p->type & CONST_DEFAULT))
756 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
758 _asn1_str_cpy (name2, sizeof (name2), name_root);
759 _asn1_str_cat (name2, sizeof (name2), ".");
760 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
761 p3 = asn1_find_node (node, name2);
762 if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
763 || !(p3->type & CONST_ASSIGN))
764 return ASN1_ELEMENT_NOT_FOUND;
769 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
772 _asn1_str_cat (name2, sizeof (name2), ".");
773 _asn1_str_cat (name2, sizeof (name2),
778 tlen = strlen (name2);
780 _asn1_set_value (p2, name2, tlen + 1);
810 p = _asn1_find_up (p);
817 /******************************************************************/
818 /* Function : _asn1_type_set_config */
819 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
820 /* in the fields of the SET elements. */
822 /* node: root of an ASN1 element. */
824 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
825 /* otherwise ASN1_SUCCESS */
826 /******************************************************************/
828 _asn1_type_set_config (asn1_node node)
834 return ASN1_ELEMENT_NOT_FOUND;
839 while (!((p == node) && (move == UP)))
843 if (type_field (p->type) == ASN1_ETYPE_SET)
848 if (type_field (p2->type) != ASN1_ETYPE_TAG)
849 p2->type |= CONST_SET | CONST_NOT_USED;
880 p = _asn1_find_up (p);
887 /******************************************************************/
888 /* Function : _asn1_check_identifier */
889 /* Description: checks the definitions of all the identifiers */
890 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
891 /* The _asn1_identifierMissing global variable is filled if */
894 /* node: root of an ASN1 element. */
896 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
897 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
898 /* otherwise ASN1_SUCCESS */
899 /******************************************************************/
901 _asn1_check_identifier (asn1_node node)
904 char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
907 return ASN1_ELEMENT_NOT_FOUND;
912 if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
914 _asn1_str_cpy (name2, sizeof (name2), node->name);
915 _asn1_str_cat (name2, sizeof (name2), ".");
916 _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
917 p2 = asn1_find_node (node, name2);
921 _asn1_strcpy (_asn1_identifierMissing, p->value);
923 _asn1_strcpy (_asn1_identifierMissing, "(null)");
924 return ASN1_IDENTIFIER_NOT_FOUND;
927 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
928 (p->type & CONST_DEFAULT))
931 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
933 _asn1_str_cpy (name2, sizeof (name2), node->name);
934 _asn1_str_cat (name2, sizeof (name2), ".");
935 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
936 _asn1_strcpy (_asn1_identifierMissing, p2->value);
937 p2 = asn1_find_node (node, name2);
938 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
939 !(p2->type & CONST_ASSIGN))
940 return ASN1_IDENTIFIER_NOT_FOUND;
942 _asn1_identifierMissing[0] = 0;
945 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
946 (p->type & CONST_ASSIGN))
949 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
951 if (p2->value && !isdigit (p2->value[0]))
953 _asn1_str_cpy (name2, sizeof (name2), node->name);
954 _asn1_str_cat (name2, sizeof (name2), ".");
955 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
956 _asn1_strcpy (_asn1_identifierMissing, p2->value);
957 p2 = asn1_find_node (node, name2);
958 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
959 || !(p2->type & CONST_ASSIGN))
960 return ASN1_IDENTIFIER_NOT_FOUND;
962 _asn1_identifierMissing[0] = 0;
977 p = _asn1_find_up (p);
996 /******************************************************************/
997 /* Function : _asn1_set_default_tag */
998 /* Description: sets the default IMPLICIT or EXPLICIT property in */
999 /* the tagged elements that don't have this declaration. */
1001 /* node: pointer to a DEFINITIONS element. */
1003 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
1004 /* a DEFINITIONS element, */
1005 /* otherwise ASN1_SUCCESS */
1006 /******************************************************************/
1008 _asn1_set_default_tag (asn1_node node)
1012 if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
1013 return ASN1_ELEMENT_NOT_FOUND;
1018 if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
1019 !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1021 if (node->type & CONST_EXPLICIT)
1022 p->type |= CONST_EXPLICIT;
1024 p->type |= CONST_IMPLICIT;
1037 p = _asn1_find_up (p);
1052 return ASN1_SUCCESS;