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];
111 if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?')
113 n_start = strchr(n_start, '.');
117 else if (p->name[0] != 0)
118 { /* has *pointer got a name ? */
119 n_end = strchr (n_start, '.'); /* search the first dot */
122 nsize = n_end - n_start;
123 memcpy (n, n_start, nsize);
128 nhash = hash_pjw_bare (n, nsize);
132 nsize = _asn1_str_cpy (n, sizeof (n), n_start);
133 nhash = hash_pjw_bare (n, nsize);
140 if (nhash == p->name_hash && (!strcmp (p->name, n)))
150 { /* *pointer doesn't have a name */
156 { /* Has the end of NAME been reached? */
157 n_end = strchr (n_start, '.'); /* search the next dot */
160 nsize = n_end - n_start;
161 memcpy (n, n_start, nsize);
166 nhash = hash_pjw_bare (n, nsize);
170 nsize = _asn1_str_cpy (n, sizeof (n), n_start);
171 nhash = hash_pjw_bare (n, nsize);
182 /* The identifier "?LAST" indicates the last element
183 in the right chain. */
184 if (n[0] == '?' && n[1] == 'L') /* ?LAST */
193 if (p->name_hash == nhash && !strcmp (p->name, n))
207 /******************************************************************/
208 /* Function : _asn1_set_value */
209 /* Description: sets the field VALUE in a NODE_ASN element. The */
210 /* previous value (if exist) will be lost */
212 /* node: element pointer. */
213 /* value: pointer to the value that you want to set. */
214 /* len: character number of value. */
215 /* Return: pointer to the NODE_ASN element. */
216 /******************************************************************/
218 _asn1_set_value (asn1_node node, const void *value, unsigned int len)
224 if (node->value != node->small_value)
233 if (len < sizeof (node->small_value))
235 node->value = node->small_value;
239 node->value = malloc (len);
240 if (node->value == NULL)
243 node->value_len = len;
245 memcpy (node->value, value, len);
249 /******************************************************************/
250 /* Function : _asn1_set_value_lv */
251 /* Description: sets the field VALUE in a NODE_ASN element. The */
252 /* previous value (if exist) will be lost. The value */
253 /* given is stored as an length-value format (LV */
255 /* node: element pointer. */
256 /* value: pointer to the value that you want to set. */
257 /* len: character number of value. */
258 /* Return: pointer to the NODE_ASN element. */
259 /******************************************************************/
261 _asn1_set_value_lv (asn1_node node, const void *value, unsigned int len)
269 asn1_length_der (len, NULL, &len2);
270 temp = malloc (len + len2);
274 asn1_octet_der (value, len, temp, &len2);
275 return _asn1_set_value_m (node, temp, len2);
278 /* the same as _asn1_set_value except that it sets an already malloc'ed
282 _asn1_set_value_m (asn1_node node, void *value, unsigned int len)
289 if (node->value != node->small_value)
299 node->value_len = len;
304 /******************************************************************/
305 /* Function : _asn1_append_value */
306 /* Description: appends to the field VALUE in a NODE_ASN element. */
309 /* node: element pointer. */
310 /* value: pointer to the value that you want to be appended. */
311 /* len: character number of value. */
312 /* Return: pointer to the NODE_ASN element. */
313 /******************************************************************/
315 _asn1_append_value (asn1_node node, const void *value, unsigned int len)
319 if (node->value != NULL && node->value != node->small_value)
321 /* value is allocated */
322 int prev_len = node->value_len;
323 node->value_len += len;
324 node->value = realloc (node->value, node->value_len);
325 if (node->value == NULL)
330 memcpy (&node->value[prev_len], value, len);
334 else if (node->value == node->small_value)
336 /* value is in node */
337 int prev_len = node->value_len;
338 node->value_len += len;
339 node->value = malloc (node->value_len);
340 if (node->value == NULL)
345 memcpy (node->value, node->small_value, prev_len);
346 memcpy (&node->value[prev_len], value, len);
350 else /* node->value == NULL */
351 return _asn1_set_value (node, value, len);
354 /******************************************************************/
355 /* Function : _asn1_set_name */
356 /* Description: sets the field NAME in a NODE_ASN element. The */
357 /* previous value (if exist) will be lost */
359 /* node: element pointer. */
360 /* name: a null terminated string with the name that you want */
362 /* Return: pointer to the NODE_ASN element. */
363 /******************************************************************/
365 _asn1_set_name (asn1_node node, const char *name)
375 node->name_hash = hash_pjw_bare (node->name, 0);
379 nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
380 node->name_hash = hash_pjw_bare (node->name, nsize);
385 /******************************************************************/
386 /* Function : _asn1_cpy_name */
387 /* Description: copies the field NAME in a NODE_ASN element. */
389 /* dst: a dest element pointer. */
390 /* src: a source element pointer. */
391 /* Return: pointer to the NODE_ASN element. */
392 /******************************************************************/
394 _asn1_cpy_name (asn1_node dst, asn1_node src)
402 dst->name_hash = hash_pjw_bare (dst->name, 0);
406 _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
407 dst->name_hash = src->name_hash;
412 /******************************************************************/
413 /* Function : _asn1_set_right */
414 /* Description: sets the field RIGHT in a NODE_ASN element. */
416 /* node: element pointer. */
417 /* right: pointer to a NODE_ASN element that you want be pointed*/
419 /* Return: pointer to *NODE. */
420 /******************************************************************/
422 _asn1_set_right (asn1_node node, asn1_node right)
430 if (right->up == NULL)
431 right->up = node->up;
437 /******************************************************************/
438 /* Function : _asn1_get_last_right */
439 /* Description: return the last element along the right chain. */
441 /* node: starting element pointer. */
442 /* Return: pointer to the last element along the right chain. */
443 /******************************************************************/
445 _asn1_get_last_right (asn1_node node)
457 /******************************************************************/
458 /* Function : _asn1_remove_node */
459 /* Description: gets free the memory allocated for an NODE_ASN */
460 /* element (not the elements pointed by it). */
462 /* node: NODE_ASN element pointer. */
463 /* flags: ASN1_DELETE_FLAG_* */
464 /******************************************************************/
466 _asn1_remove_node (asn1_node node, unsigned int flags)
471 if (node->value != NULL)
473 if (flags & ASN1_DELETE_FLAG_ZEROIZE)
475 safe_memset(node->value, 0, node->value_len);
478 if (node->value != node->small_value)
484 /******************************************************************/
485 /* Function : _asn1_find_up */
486 /* Description: return the father of the NODE_ASN element. */
488 /* node: NODE_ASN element pointer. */
489 /* Return: Null if not found. */
490 /******************************************************************/
492 _asn1_find_up (asn1_node node)
501 while ((p->left != NULL) && (p->left->right == p))
507 /******************************************************************/
508 /* Function : _asn1_delete_list */
509 /* Description: deletes the list elements (not the elements */
510 /* pointed by them). */
511 /******************************************************************/
513 _asn1_delete_list (void)
515 list_type *listElement;
519 listElement = firstElement;
520 firstElement = firstElement->next;
525 /******************************************************************/
526 /* Function : _asn1_delete_list_and nodes */
527 /* Description: deletes the list elements and the elements */
528 /* pointed by them. */
529 /******************************************************************/
531 _asn1_delete_list_and_nodes (void)
533 list_type *listElement;
537 listElement = firstElement;
538 firstElement = firstElement->next;
539 _asn1_remove_node (listElement->node, 0);
546 _asn1_ltostr (long v, char *str)
549 char temp[LTOSTR_MAX_SIZE];
566 temp[start + count] = '0' + (char) r;
572 for (k = 0; k < count; k++)
573 str[k + start] = temp[start + count - k - 1];
574 str[count + start] = 0;
579 /******************************************************************/
580 /* Function : _asn1_change_integer_value */
581 /* Description: converts into DER coding the value assign to an */
582 /* INTEGER constant. */
584 /* node: root of an ASN1element. */
586 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
587 /* otherwise ASN1_SUCCESS */
588 /******************************************************************/
590 _asn1_change_integer_value (asn1_node node)
593 unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
594 unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
598 return ASN1_ELEMENT_NOT_FOUND;
603 if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
604 && (p->type & CONST_ASSIGN))
608 _asn1_convert_integer (p->value, val, sizeof (val), &len);
609 asn1_octet_der (val, len, val2, &len);
610 _asn1_set_value (p, val2, len);
628 p = _asn1_get_up (p);
648 /******************************************************************/
649 /* Function : _asn1_expand_object_id */
650 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
652 /* node: root of an ASN1 element. */
654 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
655 /* otherwise ASN1_SUCCESS */
656 /******************************************************************/
658 _asn1_expand_object_id (asn1_node node)
660 asn1_node p, p2, p3, p4, p5;
661 char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
665 return ASN1_ELEMENT_NOT_FOUND;
667 _asn1_str_cpy (name_root, sizeof (name_root), node->name);
672 while (!((p == node) && (move == UP)))
676 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
677 && (p->type & CONST_ASSIGN))
680 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
682 if (p2->value && !isdigit (p2->value[0]))
684 _asn1_str_cpy (name2, sizeof (name2), name_root);
685 _asn1_str_cat (name2, sizeof (name2), ".");
686 _asn1_str_cat (name2, sizeof (name2),
688 p3 = asn1_find_node (node, name2);
690 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
691 || !(p3->type & CONST_ASSIGN))
692 return ASN1_ELEMENT_NOT_FOUND;
693 _asn1_set_down (p, p2->right);
694 _asn1_remove_node (p2, 0);
699 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
702 _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
703 _asn1_set_name (p5, p4->name);
704 tlen = _asn1_strlen (p4->value);
706 _asn1_set_value (p5, p4->value, tlen + 1);
709 _asn1_set_right (p5, p->down);
710 _asn1_set_down (p, p5);
714 _asn1_set_right (p5, p2->right);
715 _asn1_set_right (p2, p5);
753 p = _asn1_get_up (p);
757 /*******************************/
759 /*******************************/
763 while (!((p == node) && (move == UP)))
767 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
768 (p->type & CONST_DEFAULT))
771 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
773 _asn1_str_cpy (name2, sizeof (name2), name_root);
774 _asn1_str_cat (name2, sizeof (name2), ".");
775 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
776 p3 = asn1_find_node (node, name2);
777 if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
778 || !(p3->type & CONST_ASSIGN))
779 return ASN1_ELEMENT_NOT_FOUND;
784 if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
787 _asn1_str_cat (name2, sizeof (name2), ".");
788 _asn1_str_cat (name2, sizeof (name2),
793 tlen = strlen (name2);
795 _asn1_set_value (p2, name2, tlen + 1);
825 p = _asn1_get_up (p);
832 /******************************************************************/
833 /* Function : _asn1_type_set_config */
834 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
835 /* in the fields of the SET elements. */
837 /* node: root of an ASN1 element. */
839 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
840 /* otherwise ASN1_SUCCESS */
841 /******************************************************************/
843 _asn1_type_set_config (asn1_node node)
849 return ASN1_ELEMENT_NOT_FOUND;
854 while (!((p == node) && (move == UP)))
858 if (type_field (p->type) == ASN1_ETYPE_SET)
863 if (type_field (p2->type) != ASN1_ETYPE_TAG)
864 p2->type |= CONST_SET | CONST_NOT_USED;
895 p = _asn1_get_up (p);
902 /******************************************************************/
903 /* Function : _asn1_check_identifier */
904 /* Description: checks the definitions of all the identifiers */
905 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
906 /* The _asn1_identifierMissing global variable is filled if */
909 /* node: root of an ASN1 element. */
911 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
912 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
913 /* otherwise ASN1_SUCCESS */
914 /******************************************************************/
916 _asn1_check_identifier (asn1_node node)
919 char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
922 return ASN1_ELEMENT_NOT_FOUND;
927 if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
929 _asn1_str_cpy (name2, sizeof (name2), node->name);
930 _asn1_str_cat (name2, sizeof (name2), ".");
931 _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
932 p2 = asn1_find_node (node, name2);
936 _asn1_strcpy (_asn1_identifierMissing, p->value);
938 _asn1_strcpy (_asn1_identifierMissing, "(null)");
939 return ASN1_IDENTIFIER_NOT_FOUND;
942 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
943 (p->type & CONST_DEFAULT))
946 if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
948 _asn1_str_cpy (name2, sizeof (name2), node->name);
949 _asn1_str_cat (name2, sizeof (name2), ".");
950 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
951 _asn1_strcpy (_asn1_identifierMissing, p2->value);
952 p2 = asn1_find_node (node, name2);
953 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
954 !(p2->type & CONST_ASSIGN))
955 return ASN1_IDENTIFIER_NOT_FOUND;
957 _asn1_identifierMissing[0] = 0;
960 else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
961 (p->type & CONST_ASSIGN))
964 if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
966 if (p2->value && !isdigit (p2->value[0]))
968 _asn1_str_cpy (name2, sizeof (name2), node->name);
969 _asn1_str_cat (name2, sizeof (name2), ".");
970 _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
971 _asn1_strcpy (_asn1_identifierMissing, p2->value);
972 p2 = asn1_find_node (node, name2);
973 if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
974 || !(p2->type & CONST_ASSIGN))
975 return ASN1_IDENTIFIER_NOT_FOUND;
977 _asn1_identifierMissing[0] = 0;
992 p = _asn1_get_up (p);
1007 return ASN1_SUCCESS;
1011 /******************************************************************/
1012 /* Function : _asn1_set_default_tag */
1013 /* Description: sets the default IMPLICIT or EXPLICIT property in */
1014 /* the tagged elements that don't have this declaration. */
1016 /* node: pointer to a DEFINITIONS element. */
1018 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
1019 /* a DEFINITIONS element, */
1020 /* otherwise ASN1_SUCCESS */
1021 /******************************************************************/
1023 _asn1_set_default_tag (asn1_node node)
1027 if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
1028 return ASN1_ELEMENT_NOT_FOUND;
1033 if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
1034 !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1036 if (node->type & CONST_EXPLICIT)
1037 p->type |= CONST_EXPLICIT;
1039 p->type |= CONST_IMPLICIT;
1052 p = _asn1_get_up (p);
1067 return ASN1_SUCCESS;