2 * Copyright (C) 2002-2012 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 /*****************************************************/
24 /* File: structure.c */
25 /* Description: Functions to create and delete an */
27 /*****************************************************/
31 #include <structure.h>
32 #include "parser_aux.h"
36 extern char _asn1_identifierMissing
[];
39 /******************************************************/
40 /* Function : _asn1_add_single_node */
41 /* Description: creates a new NODE_ASN element. */
43 /* type: type of the new element (see TYPE_ */
44 /* and CONST_ constants). */
45 /* Return: pointer to the new element. */
46 /******************************************************/
48 _asn1_add_single_node (unsigned int type
)
52 punt
= calloc (1, sizeof (struct asn1_node_st
));
62 /******************************************************************/
63 /* Function : _asn1_find_left */
64 /* Description: returns the NODE_ASN element with RIGHT field that*/
65 /* points the element NODE. */
67 /* node: NODE_ASN element pointer. */
68 /* Return: NULL if not found. */
69 /******************************************************************/
71 _asn1_find_left (asn1_node node
)
73 if ((node
== NULL
) || (node
->left
== NULL
) || (node
->left
->down
== node
))
81 _asn1_create_static_structure (asn1_node pointer
, char *output_file_name
,
88 file
= fopen (output_file_name
, "w");
91 return ASN1_FILE_NOT_FOUND
;
93 fprintf (file
, "#if HAVE_CONFIG_H\n");
94 fprintf (file
, "# include \"config.h\"\n");
95 fprintf (file
, "#endif\n\n");
97 fprintf (file
, "#include <libtasn1.h>\n\n");
99 fprintf (file
, "const asn1_static_node_t %s[] = {\n", vector_name
);
105 fprintf (file
, " { ");
108 fprintf (file
, "\"%s\", ", p
->name
);
110 fprintf (file
, "NULL, ");
118 fprintf (file
, "%lu, ", t
);
121 fprintf (file
, "\"%s\"},\n", p
->value
);
123 fprintf (file
, "NULL },\n");
137 p
= _asn1_find_up (p
);
152 fprintf (file
, " { NULL, 0, NULL }\n};\n");
162 * @array: specify the array that contains ASN.1 declarations
163 * @definitions: return the pointer to the structure created by
164 * *ARRAY ASN.1 declarations
165 * @errorDescription: return the error description.
167 * Creates the structures needed to manage the ASN.1 definitions.
168 * @array is a vector created by asn1_parser2array().
170 * Returns: %ASN1_SUCCESS if structure was created correctly,
171 * %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL,
172 * %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier
173 * that is not defined (see @errorDescription for more information),
174 * %ASN1_ARRAY_ERROR if the array pointed by @array is wrong.
177 asn1_array2tree (const asn1_static_node_t
* array
, asn1_node
* definitions
,
178 char *errorDescription
)
180 asn1_node p
, p_last
= NULL
;
186 if (*definitions
!= NULL
)
187 return ASN1_ELEMENT_NOT_EMPTY
;
192 while (array
[k
].value
|| array
[k
].type
|| array
[k
].name
)
194 p
= _asn1_add_static_node (array
[k
].type
& (~CONST_DOWN
));
196 _asn1_set_name (p
, array
[k
].name
);
198 _asn1_set_value (p
, array
[k
].value
, strlen (array
[k
].value
) + 1);
200 if (*definitions
== NULL
)
204 _asn1_set_down (p_last
, p
);
205 else if (move
== RIGHT
)
206 _asn1_set_right (p_last
, p
);
210 if (array
[k
].type
& CONST_DOWN
)
212 else if (array
[k
].type
& CONST_RIGHT
)
218 if (p_last
== *definitions
)
221 p_last
= _asn1_find_up (p_last
);
226 if (p_last
->type
& CONST_RIGHT
)
228 p_last
->type
&= ~CONST_RIGHT
;
237 if (p_last
== *definitions
)
239 result
= _asn1_check_identifier (*definitions
);
240 if (result
== ASN1_SUCCESS
)
242 _asn1_change_integer_value (*definitions
);
243 _asn1_expand_object_id (*definitions
);
248 result
= ASN1_ARRAY_ERROR
;
251 if (errorDescription
!= NULL
)
253 if (result
== ASN1_IDENTIFIER_NOT_FOUND
)
255 Estrcpy (errorDescription
, ":: identifier '");
256 Estrcat (errorDescription
, _asn1_identifierMissing
);
257 Estrcat (errorDescription
, "' not found");
260 errorDescription
[0] = 0;
263 if (result
!= ASN1_SUCCESS
)
265 _asn1_delete_list_and_nodes ();
269 _asn1_delete_list ();
275 * asn1_delete_structure:
276 * @structure: pointer to the structure that you want to delete.
278 * Deletes the structure *@structure. At the end, *@structure is set
281 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
282 * *@structure was NULL.
285 asn1_delete_structure (asn1_node
* structure
)
289 if (*structure
== NULL
)
290 return ASN1_ELEMENT_NOT_FOUND
;
304 p3
= _asn1_find_up (p
);
305 _asn1_set_down (p3
, p2
);
306 _asn1_remove_node (p
);
311 p3
= _asn1_find_left (p
);
314 p3
= _asn1_find_up (p
);
316 _asn1_set_down (p3
, p2
);
320 p
->right
->left
= NULL
;
324 _asn1_set_right (p3
, p2
);
325 _asn1_remove_node (p
);
338 * asn1_delete_element:
339 * @structure: pointer to the structure that contains the element you
341 * @element_name: element's name you want to delete.
343 * Deletes the element named *@element_name inside *@structure.
345 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
346 * the @element_name was not found.
349 asn1_delete_element (asn1_node structure
, const char *element_name
)
351 asn1_node p2
, p3
, source_node
;
353 source_node
= asn1_find_node (structure
, element_name
);
355 if (source_node
== NULL
)
356 return ASN1_ELEMENT_NOT_FOUND
;
358 p2
= source_node
->right
;
359 p3
= _asn1_find_left (source_node
);
362 p3
= _asn1_find_up (source_node
);
364 _asn1_set_down (p3
, p2
);
365 else if (source_node
->right
)
366 source_node
->right
->left
= NULL
;
369 _asn1_set_right (p3
, p2
);
371 return asn1_delete_structure (&source_node
);
375 _asn1_copy_structure3 (asn1_node source_node
)
377 asn1_node dest_node
, p_s
, p_d
, p_d_prev
;
380 if (source_node
== NULL
)
383 dest_node
= _asn1_add_single_node (source_node
->type
);
394 if (p_s
->name
[0] != 0)
395 _asn1_cpy_name (p_d
, p_s
);
397 _asn1_set_value (p_d
, p_s
->value
, p_s
->value_len
);
402 p_d
= _asn1_add_single_node (p_s
->type
);
403 _asn1_set_down (p_d_prev
, p_d
);
408 if (p_s
== source_node
)
416 p_d
= _asn1_add_single_node (p_s
->type
);
417 _asn1_set_right (p_d_prev
, p_d
);
422 p_s
= _asn1_find_up (p_s
);
423 p_d
= _asn1_find_up (p_d
);
426 while (p_s
!= source_node
);
433 _asn1_copy_structure2 (asn1_node root
, const char *source_name
)
435 asn1_node source_node
;
437 source_node
= asn1_find_node (root
, source_name
);
439 return _asn1_copy_structure3 (source_node
);
445 _asn1_type_choice_config (asn1_node node
)
447 asn1_node p
, p2
, p3
, p4
;
451 return ASN1_ELEMENT_NOT_FOUND
;
456 while (!((p
== node
) && (move
== UP
)))
460 if ((type_field (p
->type
) == TYPE_CHOICE
) && (p
->type
& CONST_TAG
))
465 if (type_field (p2
->type
) != TYPE_TAG
)
467 p2
->type
|= CONST_TAG
;
468 p3
= _asn1_find_left (p2
);
471 if (type_field (p3
->type
) == TYPE_TAG
)
473 p4
= _asn1_add_single_node (p3
->type
);
474 tlen
= _asn1_strlen (p3
->value
);
476 _asn1_set_value (p4
, p3
->value
, tlen
+ 1);
477 _asn1_set_right (p4
, p2
->down
);
478 _asn1_set_down (p2
, p4
);
480 p3
= _asn1_find_left (p3
);
485 p
->type
&= ~(CONST_TAG
);
490 if (type_field (p2
->type
) == TYPE_TAG
)
491 asn1_delete_structure (&p2
);
522 p
= _asn1_find_up (p
);
530 _asn1_expand_identifier (asn1_node
* node
, asn1_node root
)
533 char name2
[ASN1_MAX_NAME_SIZE
+ 2];
537 return ASN1_ELEMENT_NOT_FOUND
;
542 while (!((p
== *node
) && (move
== UP
)))
546 if (type_field (p
->type
) == TYPE_IDENTIFIER
)
548 snprintf(name2
, sizeof (name2
), "%s.%s", root
->name
, p
->value
);
549 p2
= _asn1_copy_structure2 (root
, name2
);
552 return ASN1_IDENTIFIER_NOT_FOUND
;
554 _asn1_cpy_name (p2
, p
);
555 p2
->right
= p
->right
;
564 _asn1_set_right (p3
, p2
->down
);
565 _asn1_set_down (p2
, p
->down
);
568 p3
= _asn1_find_left (p
);
570 _asn1_set_right (p3
, p2
);
573 p3
= _asn1_find_up (p
);
575 _asn1_set_down (p3
, p2
);
582 if (p
->type
& CONST_SIZE
)
583 p2
->type
|= CONST_SIZE
;
584 if (p
->type
& CONST_TAG
)
585 p2
->type
|= CONST_TAG
;
586 if (p
->type
& CONST_OPTION
)
587 p2
->type
|= CONST_OPTION
;
588 if (p
->type
& CONST_DEFAULT
)
589 p2
->type
|= CONST_DEFAULT
;
590 if (p
->type
& CONST_SET
)
591 p2
->type
|= CONST_SET
;
592 if (p
->type
& CONST_NOT_USED
)
593 p2
->type
|= CONST_NOT_USED
;
597 _asn1_remove_node (p
);
629 p
= _asn1_find_up (p
);
637 * asn1_create_element:
638 * @definitions: pointer to the structure returned by "parser_asn1" function
639 * @source_name: the name of the type of the new structure (must be
640 * inside p_structure).
641 * @element: pointer to the structure created.
643 * Creates a structure of type @source_name. Example using
646 * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
648 * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
649 * @source_name is not known.
652 asn1_create_element (asn1_node definitions
, const char *source_name
,
658 dest_node
= _asn1_copy_structure2 (definitions
, source_name
);
660 if (dest_node
== NULL
)
661 return ASN1_ELEMENT_NOT_FOUND
;
663 _asn1_set_name (dest_node
, "");
665 res
= _asn1_expand_identifier (&dest_node
, definitions
);
666 _asn1_type_choice_config (dest_node
);
668 *element
= dest_node
;
675 * asn1_print_structure:
676 * @out: pointer to the output file (e.g. stdout).
677 * @structure: pointer to the structure that you want to visit.
678 * @name: an element of the structure
679 * @mode: specify how much of the structure to print, can be
680 * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
681 * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
683 * Prints on the @out file descriptor the structure's tree starting
684 * from the @name element inside the structure @structure.
687 asn1_print_structure (FILE * out
, asn1_node structure
, const char *name
,
691 int k
, indent
= 0, len
, len2
, len3
;
696 root
= asn1_find_node (structure
, name
);
704 if (mode
== ASN1_PRINT_ALL
)
706 for (k
= 0; k
< indent
; k
++)
708 fprintf (out
, "name:");
710 fprintf (out
, "%s ", p
->name
);
712 fprintf (out
, "NULL ");
716 switch (type_field (p
->type
))
723 for (k
= 0; k
< indent
; k
++)
725 fprintf (out
, "name:");
727 fprintf (out
, "%s ", p
->name
);
729 fprintf (out
, "NULL ");
733 if (mode
!= ASN1_PRINT_NAME
)
735 switch (type_field (p
->type
))
738 if (mode
== ASN1_PRINT_ALL
)
739 fprintf (out
, "type:CONST");
742 if (mode
== ASN1_PRINT_ALL
)
743 fprintf (out
, "type:TAG");
746 if (mode
== ASN1_PRINT_ALL
)
747 fprintf (out
, "type:SIZE");
750 fprintf (out
, "type:DEFAULT");
753 fprintf (out
, "type:NULL");
755 case TYPE_IDENTIFIER
:
756 fprintf (out
, "type:IDENTIFIER");
759 fprintf (out
, "type:INTEGER");
761 case TYPE_ENUMERATED
:
762 fprintf (out
, "type:ENUMERATED");
765 fprintf (out
, "type:TIME");
768 fprintf (out
, "type:BOOLEAN");
771 fprintf (out
, "type:SEQUENCE");
773 case TYPE_BIT_STRING
:
774 fprintf (out
, "type:BIT_STR");
776 case TYPE_OCTET_STRING
:
777 fprintf (out
, "type:OCT_STR");
779 case TYPE_GENERALSTRING
:
780 fprintf (out
, "type:GENERALSTRING");
782 case TYPE_SEQUENCE_OF
:
783 fprintf (out
, "type:SEQ_OF");
786 fprintf (out
, "type:OBJ_ID");
789 fprintf (out
, "type:ANY");
792 fprintf (out
, "type:SET");
795 fprintf (out
, "type:SET_OF");
798 fprintf (out
, "type:CHOICE");
800 case TYPE_DEFINITIONS
:
801 fprintf (out
, "type:DEFINITIONS");
808 if ((mode
== ASN1_PRINT_NAME_TYPE_VALUE
) || (mode
== ASN1_PRINT_ALL
))
810 switch (type_field (p
->type
))
813 if (mode
== ASN1_PRINT_ALL
)
815 fprintf (out
, " value:%s", p
->value
);
818 if (mode
== ASN1_PRINT_ALL
)
820 fprintf (out
, " value:%s", p
->value
);
823 if (mode
== ASN1_PRINT_ALL
)
825 fprintf (out
, " value:%s", p
->value
);
829 fprintf (out
, " value:%s", p
->value
);
830 else if (p
->type
& CONST_TRUE
)
831 fprintf (out
, " value:TRUE");
832 else if (p
->type
& CONST_FALSE
)
833 fprintf (out
, " value:FALSE");
835 case TYPE_IDENTIFIER
:
837 fprintf (out
, " value:%s", p
->value
);
843 len
= asn1_get_length_der (p
->value
, p
->value_len
, &len2
);
844 fprintf (out
, " value:0x");
846 for (k
= 0; k
< len
; k
++)
847 fprintf (out
, "%02x", (p
->value
)[k
+ len2
]);
850 case TYPE_ENUMERATED
:
854 len
= asn1_get_length_der (p
->value
, p
->value_len
, &len2
);
855 fprintf (out
, " value:0x");
857 for (k
= 0; k
< len
; k
++)
858 fprintf (out
, "%02x", (p
->value
)[k
+ len2
]);
863 fprintf (out
, " value:%s", p
->value
);
868 if (p
->value
[0] == 'T')
869 fprintf (out
, " value:TRUE");
870 else if (p
->value
[0] == 'F')
871 fprintf (out
, " value:FALSE");
874 case TYPE_BIT_STRING
:
878 len
= asn1_get_length_der (p
->value
, p
->value_len
, &len2
);
881 fprintf (out
, " value(%i):",
882 (len
- 1) * 8 - (p
->value
[len2
]));
883 for (k
= 1; k
< len
; k
++)
884 fprintf (out
, "%02x", (p
->value
)[k
+ len2
]);
888 case TYPE_OCTET_STRING
:
892 len
= asn1_get_length_der (p
->value
, p
->value_len
, &len2
);
893 fprintf (out
, " value:");
895 for (k
= 0; k
< len
; k
++)
896 fprintf (out
, "%02x", (p
->value
)[k
+ len2
]);
899 case TYPE_GENERALSTRING
:
903 len
= asn1_get_length_der (p
->value
, p
->value_len
, &len2
);
904 fprintf (out
, " value:");
906 for (k
= 0; k
< len
; k
++)
907 fprintf (out
, "%02x", (p
->value
)[k
+ len2
]);
912 fprintf (out
, " value:%s", p
->value
);
918 len2
= asn1_get_length_der (p
->value
, p
->value_len
, &len3
);
919 fprintf (out
, " value:");
921 for (k
= 0; k
< len2
; k
++)
922 fprintf (out
, "%02x", (p
->value
)[k
+ len3
]);
928 case TYPE_DEFINITIONS
:
929 case TYPE_SEQUENCE_OF
:
938 if (mode
== ASN1_PRINT_ALL
)
940 if (p
->type
& 0x1FFFFF00)
942 fprintf (out
, " attr:");
943 if (p
->type
& CONST_UNIVERSAL
)
944 fprintf (out
, "UNIVERSAL,");
945 if (p
->type
& CONST_PRIVATE
)
946 fprintf (out
, "PRIVATE,");
947 if (p
->type
& CONST_APPLICATION
)
948 fprintf (out
, "APPLICATION,");
949 if (p
->type
& CONST_EXPLICIT
)
950 fprintf (out
, "EXPLICIT,");
951 if (p
->type
& CONST_IMPLICIT
)
952 fprintf (out
, "IMPLICIT,");
953 if (p
->type
& CONST_TAG
)
954 fprintf (out
, "TAG,");
955 if (p
->type
& CONST_DEFAULT
)
956 fprintf (out
, "DEFAULT,");
957 if (p
->type
& CONST_TRUE
)
958 fprintf (out
, "TRUE,");
959 if (p
->type
& CONST_FALSE
)
960 fprintf (out
, "FALSE,");
961 if (p
->type
& CONST_LIST
)
962 fprintf (out
, "LIST,");
963 if (p
->type
& CONST_MIN_MAX
)
964 fprintf (out
, "MIN_MAX,");
965 if (p
->type
& CONST_OPTION
)
966 fprintf (out
, "OPTION,");
967 if (p
->type
& CONST_1_PARAM
)
968 fprintf (out
, "1_PARAM,");
969 if (p
->type
& CONST_SIZE
)
970 fprintf (out
, "SIZE,");
971 if (p
->type
& CONST_DEFINED_BY
)
972 fprintf (out
, "DEF_BY,");
973 if (p
->type
& CONST_GENERALIZED
)
974 fprintf (out
, "GENERALIZED,");
975 if (p
->type
& CONST_UTC
)
976 fprintf (out
, "UTC,");
977 if (p
->type
& CONST_SET
)
978 fprintf (out
, "SET,");
979 if (p
->type
& CONST_NOT_USED
)
980 fprintf (out
, "NOT_USED,");
981 if (p
->type
& CONST_ASSIGN
)
982 fprintf (out
, "ASSIGNMENT,");
986 if (mode
== ASN1_PRINT_ALL
)
992 switch (type_field (p
->type
))
1019 p
= _asn1_find_up (p
);
1039 * asn1_number_of_elements:
1040 * @element: pointer to the root of an ASN1 structure.
1041 * @name: the name of a sub-structure of ROOT.
1042 * @num: pointer to an integer where the result will be stored
1044 * Counts the number of elements of a sub-structure called NAME with
1045 * names equal to "?1","?2", ...
1047 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
1048 * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
1051 asn1_number_of_elements (asn1_node element
, const char *name
, int *num
)
1056 return ASN1_GENERIC_ERROR
;
1060 node
= asn1_find_node (element
, name
);
1062 return ASN1_ELEMENT_NOT_FOUND
;
1068 if (p
->name
[0] == '?')
1073 return ASN1_SUCCESS
;
1078 * asn1_find_structure_from_oid:
1079 * @definitions: ASN1 definitions
1080 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1082 * Search the structure that is defined just after an OID definition.
1084 * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1085 * constant string that contains the element name defined just after
1089 asn1_find_structure_from_oid (asn1_node definitions
, const char *oidValue
)
1091 char definitionsName
[ASN1_MAX_NAME_SIZE
], name
[2 * ASN1_MAX_NAME_SIZE
+ 1];
1092 char value
[ASN1_MAX_NAME_SIZE
];
1097 if ((definitions
== NULL
) || (oidValue
== NULL
))
1098 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
1101 strcpy (definitionsName
, definitions
->name
);
1102 strcat (definitionsName
, ".");
1104 /* search the OBJECT_ID into definitions */
1105 p
= definitions
->down
;
1108 if ((type_field (p
->type
) == TYPE_OBJECT_ID
) &&
1109 (p
->type
& CONST_ASSIGN
))
1111 strcpy (name
, definitionsName
);
1112 strcat (name
, p
->name
);
1114 len
= ASN1_MAX_NAME_SIZE
;
1115 result
= asn1_read_value (definitions
, name
, value
, &len
);
1117 if ((result
== ASN1_SUCCESS
) && (!strcmp (oidValue
, value
)))
1120 if (p
== NULL
) /* reach the end of ASN1 definitions */
1121 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
1129 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
1134 * @dst: Destination asn1_node node.
1135 * @dst_name: Field name in destination node.
1136 * @src: Source asn1_node node.
1137 * @src_name: Field name in source node.
1139 * Create a deep copy of a asn1_node variable.
1141 * Returns: Return %ASN1_SUCCESS on success.
1144 asn1_copy_node (asn1_node dst
, const char *dst_name
,
1145 asn1_node src
, const char *src_name
)
1147 /* FIXME: rewrite using copy_structure().
1148 * It seems quite hard to do.
1155 result
= asn1_der_coding (src
, src_name
, NULL
, &size
, NULL
);
1156 if (result
!= ASN1_MEM_ERROR
)
1159 data
= malloc (size
);
1161 return ASN1_MEM_ERROR
;
1163 result
= asn1_der_coding (src
, src_name
, data
, &size
, NULL
);
1164 if (result
!= ASN1_SUCCESS
)
1170 dst_node
= asn1_find_node (dst
, dst_name
);
1171 if (dst_node
== NULL
)
1174 return ASN1_ELEMENT_NOT_FOUND
;
1177 result
= asn1_der_decoding (&dst_node
, data
, size
, NULL
);