corrected copyright notices
[gnutls.git] / lib / minitasn1 / structure.c
blob31a5f654bbd7817649e1d8998d3f1ab0c29623bf
1 /*
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
19 * 02110-1301, USA
23 /*****************************************************/
24 /* File: structure.c */
25 /* Description: Functions to create and delete an */
26 /* ASN1 tree. */
27 /*****************************************************/
30 #include <int.h>
31 #include <structure.h>
32 #include "parser_aux.h"
33 #include <gstr.h>
36 extern char _asn1_identifierMissing[];
39 /******************************************************/
40 /* Function : _asn1_add_single_node */
41 /* Description: creates a new NODE_ASN element. */
42 /* Parameters: */
43 /* type: type of the new element (see ASN1_ETYPE_ */
44 /* and CONST_ constants). */
45 /* Return: pointer to the new element. */
46 /******************************************************/
47 asn1_node
48 _asn1_add_single_node (unsigned int type)
50 asn1_node punt;
52 punt = calloc (1, sizeof (struct asn1_node_st));
53 if (punt == NULL)
54 return NULL;
56 punt->type = type;
58 return punt;
62 /******************************************************************/
63 /* Function : _asn1_find_left */
64 /* Description: returns the NODE_ASN element with RIGHT field that*/
65 /* points the element NODE. */
66 /* Parameters: */
67 /* node: NODE_ASN element pointer. */
68 /* Return: NULL if not found. */
69 /******************************************************************/
70 asn1_node
71 _asn1_find_left (asn1_node node)
73 if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
74 return NULL;
76 return node->left;
80 int
81 _asn1_create_static_structure (asn1_node pointer, char *output_file_name,
82 char *vector_name)
84 FILE *file;
85 asn1_node p;
86 unsigned long t;
88 file = fopen (output_file_name, "w");
90 if (file == NULL)
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 %s[] = {\n", vector_name);
101 p = pointer;
103 while (p)
105 fprintf (file, " { ");
107 if (p->name[0] != 0)
108 fprintf (file, "\"%s\", ", p->name);
109 else
110 fprintf (file, "NULL, ");
112 t = p->type;
113 if (p->down)
114 t |= CONST_DOWN;
115 if (p->right)
116 t |= CONST_RIGHT;
118 fprintf (file, "%lu, ", t);
120 if (p->value)
121 fprintf (file, "\"%s\"},\n", p->value);
122 else
123 fprintf (file, "NULL },\n");
125 if (p->down)
127 p = p->down;
129 else if (p->right)
131 p = p->right;
133 else
135 while (1)
137 p = _asn1_find_up (p);
138 if (p == pointer)
140 p = NULL;
141 break;
143 if (p->right)
145 p = p->right;
146 break;
152 fprintf (file, " { NULL, 0, NULL }\n};\n");
154 fclose (file);
156 return ASN1_SUCCESS;
161 * asn1_array2tree:
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 * array, asn1_node * definitions,
178 char *errorDescription)
180 asn1_node p, p_last = NULL;
181 unsigned long k;
182 int move;
183 int result;
184 unsigned int type;
187 if (*definitions != NULL)
188 return ASN1_ELEMENT_NOT_EMPTY;
190 move = UP;
192 k = 0;
193 while (array[k].value || array[k].type || array[k].name)
195 type = convert_old_type(array[k].type);
197 p = _asn1_add_static_node (type & (~CONST_DOWN));
198 if (array[k].name)
199 _asn1_set_name (p, array[k].name);
200 if (array[k].value)
201 _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
203 if (*definitions == NULL)
204 *definitions = p;
206 if (move == DOWN)
207 _asn1_set_down (p_last, p);
208 else if (move == RIGHT)
209 _asn1_set_right (p_last, p);
211 p_last = p;
213 if (type & CONST_DOWN)
214 move = DOWN;
215 else if (type & CONST_RIGHT)
216 move = RIGHT;
217 else
219 while (1)
221 if (p_last == *definitions)
222 break;
224 p_last = _asn1_find_up (p_last);
226 if (p_last == NULL)
227 break;
229 if (p_last->type & CONST_RIGHT)
231 p_last->type &= ~CONST_RIGHT;
232 move = RIGHT;
233 break;
235 } /* while */
237 k++;
238 } /* while */
240 if (p_last == *definitions)
242 result = _asn1_check_identifier (*definitions);
243 if (result == ASN1_SUCCESS)
245 _asn1_change_integer_value (*definitions);
246 _asn1_expand_object_id (*definitions);
249 else
251 result = ASN1_ARRAY_ERROR;
254 if (errorDescription != NULL)
256 if (result == ASN1_IDENTIFIER_NOT_FOUND)
258 Estrcpy (errorDescription, ":: identifier '");
259 Estrcat (errorDescription, _asn1_identifierMissing);
260 Estrcat (errorDescription, "' not found");
262 else
263 errorDescription[0] = 0;
266 if (result != ASN1_SUCCESS)
268 _asn1_delete_list_and_nodes ();
269 *definitions = NULL;
271 else
272 _asn1_delete_list ();
274 return result;
278 * asn1_delete_structure:
279 * @structure: pointer to the structure that you want to delete.
281 * Deletes the structure *@structure. At the end, *@structure is set
282 * to NULL.
284 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
285 * *@structure was NULL.
288 asn1_delete_structure (asn1_node * structure)
290 asn1_node p, p2, p3;
292 if (*structure == NULL)
293 return ASN1_ELEMENT_NOT_FOUND;
295 p = *structure;
296 while (p)
298 if (p->down)
300 p = p->down;
302 else
303 { /* no down */
304 p2 = p->right;
305 if (p != *structure)
307 p3 = _asn1_find_up (p);
308 _asn1_set_down (p3, p2);
309 _asn1_remove_node (p);
310 p = p3;
312 else
313 { /* p==root */
314 p3 = _asn1_find_left (p);
315 if (!p3)
317 p3 = _asn1_find_up (p);
318 if (p3)
319 _asn1_set_down (p3, p2);
320 else
322 if (p->right)
323 p->right->left = NULL;
326 else
327 _asn1_set_right (p3, p2);
328 _asn1_remove_node (p);
329 p = NULL;
334 *structure = NULL;
335 return ASN1_SUCCESS;
341 * asn1_delete_element:
342 * @structure: pointer to the structure that contains the element you
343 * want to delete.
344 * @element_name: element's name you want to delete.
346 * Deletes the element named *@element_name inside *@structure.
348 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
349 * the @element_name was not found.
352 asn1_delete_element (asn1_node structure, const char *element_name)
354 asn1_node p2, p3, source_node;
356 source_node = asn1_find_node (structure, element_name);
358 if (source_node == NULL)
359 return ASN1_ELEMENT_NOT_FOUND;
361 p2 = source_node->right;
362 p3 = _asn1_find_left (source_node);
363 if (!p3)
365 p3 = _asn1_find_up (source_node);
366 if (p3)
367 _asn1_set_down (p3, p2);
368 else if (source_node->right)
369 source_node->right->left = NULL;
371 else
372 _asn1_set_right (p3, p2);
374 return asn1_delete_structure (&source_node);
377 asn1_node
378 _asn1_copy_structure3 (asn1_node source_node)
380 asn1_node dest_node, p_s, p_d, p_d_prev;
381 int move;
383 if (source_node == NULL)
384 return NULL;
386 dest_node = _asn1_add_single_node (source_node->type);
388 p_s = source_node;
389 p_d = dest_node;
391 move = DOWN;
395 if (move != UP)
397 if (p_s->name[0] != 0)
398 _asn1_cpy_name (p_d, p_s);
399 if (p_s->value)
400 _asn1_set_value (p_d, p_s->value, p_s->value_len);
401 if (p_s->down)
403 p_s = p_s->down;
404 p_d_prev = p_d;
405 p_d = _asn1_add_single_node (p_s->type);
406 _asn1_set_down (p_d_prev, p_d);
407 continue;
411 if (p_s == source_node)
412 break;
414 if (p_s->right)
416 move = RIGHT;
417 p_s = p_s->right;
418 p_d_prev = p_d;
419 p_d = _asn1_add_single_node (p_s->type);
420 _asn1_set_right (p_d_prev, p_d);
422 else
424 move = UP;
425 p_s = _asn1_find_up (p_s);
426 p_d = _asn1_find_up (p_d);
429 while (p_s != source_node);
431 return dest_node;
435 static asn1_node
436 _asn1_copy_structure2 (asn1_node root, const char *source_name)
438 asn1_node source_node;
440 source_node = asn1_find_node (root, source_name);
442 return _asn1_copy_structure3 (source_node);
447 static int
448 _asn1_type_choice_config (asn1_node node)
450 asn1_node p, p2, p3, p4;
451 int move, tlen;
453 if (node == NULL)
454 return ASN1_ELEMENT_NOT_FOUND;
456 p = node;
457 move = DOWN;
459 while (!((p == node) && (move == UP)))
461 if (move != UP)
463 if ((type_field (p->type) == ASN1_ETYPE_CHOICE) && (p->type & CONST_TAG))
465 p2 = p->down;
466 while (p2)
468 if (type_field (p2->type) != ASN1_ETYPE_TAG)
470 p2->type |= CONST_TAG;
471 p3 = _asn1_find_left (p2);
472 while (p3)
474 if (type_field (p3->type) == ASN1_ETYPE_TAG)
476 p4 = _asn1_add_single_node (p3->type);
477 tlen = _asn1_strlen (p3->value);
478 if (tlen > 0)
479 _asn1_set_value (p4, p3->value, tlen + 1);
480 _asn1_set_right (p4, p2->down);
481 _asn1_set_down (p2, p4);
483 p3 = _asn1_find_left (p3);
486 p2 = p2->right;
488 p->type &= ~(CONST_TAG);
489 p2 = p->down;
490 while (p2)
492 p3 = p2->right;
493 if (type_field (p2->type) == ASN1_ETYPE_TAG)
494 asn1_delete_structure (&p2);
495 p2 = p3;
498 move = DOWN;
500 else
501 move = RIGHT;
503 if (move == DOWN)
505 if (p->down)
506 p = p->down;
507 else
508 move = RIGHT;
511 if (p == node)
513 move = UP;
514 continue;
517 if (move == RIGHT)
519 if (p->right)
520 p = p->right;
521 else
522 move = UP;
524 if (move == UP)
525 p = _asn1_find_up (p);
528 return ASN1_SUCCESS;
532 static int
533 _asn1_expand_identifier (asn1_node * node, asn1_node root)
535 asn1_node p, p2, p3;
536 char name2[ASN1_MAX_NAME_SIZE + 2];
537 int move;
539 if (node == NULL)
540 return ASN1_ELEMENT_NOT_FOUND;
542 p = *node;
543 move = DOWN;
545 while (!((p == *node) && (move == UP)))
547 if (move != UP)
549 if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
551 snprintf(name2, sizeof (name2), "%s.%s", root->name, p->value);
552 p2 = _asn1_copy_structure2 (root, name2);
553 if (p2 == NULL)
555 return ASN1_IDENTIFIER_NOT_FOUND;
557 _asn1_cpy_name (p2, p);
558 p2->right = p->right;
559 p2->left = p->left;
560 if (p->right)
561 p->right->left = p2;
562 p3 = p->down;
563 if (p3)
565 while (p3->right)
566 p3 = p3->right;
567 _asn1_set_right (p3, p2->down);
568 _asn1_set_down (p2, p->down);
571 p3 = _asn1_find_left (p);
572 if (p3)
573 _asn1_set_right (p3, p2);
574 else
576 p3 = _asn1_find_up (p);
577 if (p3)
578 _asn1_set_down (p3, p2);
579 else
581 p2->left = NULL;
585 if (p->type & CONST_SIZE)
586 p2->type |= CONST_SIZE;
587 if (p->type & CONST_TAG)
588 p2->type |= CONST_TAG;
589 if (p->type & CONST_OPTION)
590 p2->type |= CONST_OPTION;
591 if (p->type & CONST_DEFAULT)
592 p2->type |= CONST_DEFAULT;
593 if (p->type & CONST_SET)
594 p2->type |= CONST_SET;
595 if (p->type & CONST_NOT_USED)
596 p2->type |= CONST_NOT_USED;
598 if (p == *node)
599 *node = p2;
600 _asn1_remove_node (p);
601 p = p2;
602 move = DOWN;
603 continue;
605 move = DOWN;
607 else
608 move = RIGHT;
610 if (move == DOWN)
612 if (p->down)
613 p = p->down;
614 else
615 move = RIGHT;
618 if (p == *node)
620 move = UP;
621 continue;
624 if (move == RIGHT)
626 if (p->right)
627 p = p->right;
628 else
629 move = UP;
631 if (move == UP)
632 p = _asn1_find_up (p);
635 return ASN1_SUCCESS;
640 * asn1_create_element:
641 * @definitions: pointer to the structure returned by "parser_asn1" function
642 * @source_name: the name of the type of the new structure (must be
643 * inside p_structure).
644 * @element: pointer to the structure created.
646 * Creates a structure of type @source_name. Example using
647 * "pkix.asn":
649 * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
651 * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
652 * @source_name is not known.
655 asn1_create_element (asn1_node definitions, const char *source_name,
656 asn1_node * element)
658 asn1_node dest_node;
659 int res;
661 dest_node = _asn1_copy_structure2 (definitions, source_name);
663 if (dest_node == NULL)
664 return ASN1_ELEMENT_NOT_FOUND;
666 _asn1_set_name (dest_node, "");
668 res = _asn1_expand_identifier (&dest_node, definitions);
669 _asn1_type_choice_config (dest_node);
671 *element = dest_node;
673 return res;
678 * asn1_print_structure:
679 * @out: pointer to the output file (e.g. stdout).
680 * @structure: pointer to the structure that you want to visit.
681 * @name: an element of the structure
682 * @mode: specify how much of the structure to print, can be
683 * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
684 * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
686 * Prints on the @out file descriptor the structure's tree starting
687 * from the @name element inside the structure @structure.
689 void
690 asn1_print_structure (FILE * out, asn1_node structure, const char *name,
691 int mode)
693 asn1_node p, root;
694 int k, indent = 0, len, len2, len3;
696 if (out == NULL)
697 return;
699 root = asn1_find_node (structure, name);
701 if (root == NULL)
702 return;
704 p = root;
705 while (p)
707 if (mode == ASN1_PRINT_ALL)
709 for (k = 0; k < indent; k++)
710 fprintf (out, " ");
711 fprintf (out, "name:");
712 if (p->name[0] != 0)
713 fprintf (out, "%s ", p->name);
714 else
715 fprintf (out, "NULL ");
717 else
719 switch (type_field (p->type))
721 case ASN1_ETYPE_CONSTANT:
722 case ASN1_ETYPE_TAG:
723 case ASN1_ETYPE_SIZE:
724 break;
725 default:
726 for (k = 0; k < indent; k++)
727 fprintf (out, " ");
728 fprintf (out, "name:");
729 if (p->name[0] != 0)
730 fprintf (out, "%s ", p->name);
731 else
732 fprintf (out, "NULL ");
736 if (mode != ASN1_PRINT_NAME)
738 unsigned type = type_field (p->type);
739 switch (type)
741 case ASN1_ETYPE_CONSTANT:
742 if (mode == ASN1_PRINT_ALL)
743 fprintf (out, "type:CONST");
744 break;
745 case ASN1_ETYPE_TAG:
746 if (mode == ASN1_PRINT_ALL)
747 fprintf (out, "type:TAG");
748 break;
749 case ASN1_ETYPE_SIZE:
750 if (mode == ASN1_PRINT_ALL)
751 fprintf (out, "type:SIZE");
752 break;
753 case ASN1_ETYPE_DEFAULT:
754 fprintf (out, "type:DEFAULT");
755 break;
756 case ASN1_ETYPE_IDENTIFIER:
757 fprintf (out, "type:IDENTIFIER");
758 break;
759 case ASN1_ETYPE_ANY:
760 fprintf (out, "type:ANY");
761 break;
762 case ASN1_ETYPE_CHOICE:
763 fprintf (out, "type:CHOICE");
764 break;
765 case ASN1_ETYPE_DEFINITIONS:
766 fprintf (out, "type:DEFINITIONS");
767 break;
768 CASE_HANDLED_ETYPES:
769 fprintf (out, "%s", _asn1_tags[type].desc);
770 break;
771 default:
772 break;
776 if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
778 switch (type_field (p->type))
780 case ASN1_ETYPE_CONSTANT:
781 if (mode == ASN1_PRINT_ALL)
782 if (p->value)
783 fprintf (out, " value:%s", p->value);
784 break;
785 case ASN1_ETYPE_TAG:
786 if (mode == ASN1_PRINT_ALL)
787 if (p->value)
788 fprintf (out, " value:%s", p->value);
789 break;
790 case ASN1_ETYPE_SIZE:
791 if (mode == ASN1_PRINT_ALL)
792 if (p->value)
793 fprintf (out, " value:%s", p->value);
794 break;
795 case ASN1_ETYPE_DEFAULT:
796 if (p->value)
797 fprintf (out, " value:%s", p->value);
798 else if (p->type & CONST_TRUE)
799 fprintf (out, " value:TRUE");
800 else if (p->type & CONST_FALSE)
801 fprintf (out, " value:FALSE");
802 break;
803 case ASN1_ETYPE_IDENTIFIER:
804 if (p->value)
805 fprintf (out, " value:%s", p->value);
806 break;
807 case ASN1_ETYPE_INTEGER:
808 if (p->value)
810 len2 = -1;
811 len = asn1_get_length_der (p->value, p->value_len, &len2);
812 fprintf (out, " value:0x");
813 if (len > 0)
814 for (k = 0; k < len; k++)
815 fprintf (out, "%02x", (p->value)[k + len2]);
817 break;
818 case ASN1_ETYPE_ENUMERATED:
819 if (p->value)
821 len2 = -1;
822 len = asn1_get_length_der (p->value, p->value_len, &len2);
823 fprintf (out, " value:0x");
824 if (len > 0)
825 for (k = 0; k < len; k++)
826 fprintf (out, "%02x", (p->value)[k + len2]);
828 break;
829 case ASN1_ETYPE_BOOLEAN:
830 if (p->value)
832 if (p->value[0] == 'T')
833 fprintf (out, " value:TRUE");
834 else if (p->value[0] == 'F')
835 fprintf (out, " value:FALSE");
837 break;
838 case ASN1_ETYPE_BIT_STRING:
839 if (p->value)
841 len2 = -1;
842 len = asn1_get_length_der (p->value, p->value_len, &len2);
843 if (len > 0)
845 fprintf (out, " value(%i):",
846 (len - 1) * 8 - (p->value[len2]));
847 for (k = 1; k < len; k++)
848 fprintf (out, "%02x", (p->value)[k + len2]);
851 break;
852 case ASN1_ETYPE_GENERALIZED_TIME:
853 case ASN1_ETYPE_UTC_TIME:
854 if (p->value)
856 fprintf (out, " value:");
857 for (k = 0; k < p->value_len; k++)
858 fprintf (out, "%c", (p->value)[k]);
860 break;
861 case ASN1_ETYPE_GENERALSTRING:
862 case ASN1_ETYPE_NUMERIC_STRING:
863 case ASN1_ETYPE_IA5_STRING:
864 case ASN1_ETYPE_TELETEX_STRING:
865 case ASN1_ETYPE_PRINTABLE_STRING:
866 case ASN1_ETYPE_UNIVERSAL_STRING:
867 case ASN1_ETYPE_UTF8_STRING:
868 case ASN1_ETYPE_VISIBLE_STRING:
869 if (p->value)
871 len2 = -1;
872 len = asn1_get_length_der (p->value, p->value_len, &len2);
873 fprintf (out, " value:");
874 if (len > 0)
875 for (k = 0; k < len; k++)
876 fprintf (out, "%c", (p->value)[k + len2]);
878 break;
879 case ASN1_ETYPE_BMP_STRING:
880 case ASN1_ETYPE_OCTET_STRING:
881 if (p->value)
883 len2 = -1;
884 len = asn1_get_length_der (p->value, p->value_len, &len2);
885 fprintf (out, " value:");
886 if (len > 0)
887 for (k = 0; k < len; k++)
888 fprintf (out, "%02x", (p->value)[k + len2]);
890 break;
891 case ASN1_ETYPE_OBJECT_ID:
892 if (p->value)
893 fprintf (out, " value:%s", p->value);
894 break;
895 case ASN1_ETYPE_ANY:
896 if (p->value)
898 len3 = -1;
899 len2 = asn1_get_length_der (p->value, p->value_len, &len3);
900 fprintf (out, " value:");
901 if (len2 > 0)
902 for (k = 0; k < len2; k++)
903 fprintf (out, "%02x", (p->value)[k + len3]);
905 break;
906 case ASN1_ETYPE_SET:
907 case ASN1_ETYPE_SET_OF:
908 case ASN1_ETYPE_CHOICE:
909 case ASN1_ETYPE_DEFINITIONS:
910 case ASN1_ETYPE_SEQUENCE_OF:
911 case ASN1_ETYPE_SEQUENCE:
912 case ASN1_ETYPE_NULL:
913 break;
914 default:
915 break;
919 if (mode == ASN1_PRINT_ALL)
921 if (p->type & 0x1FFFFF00)
923 fprintf (out, " attr:");
924 if (p->type & CONST_UNIVERSAL)
925 fprintf (out, "UNIVERSAL,");
926 if (p->type & CONST_PRIVATE)
927 fprintf (out, "PRIVATE,");
928 if (p->type & CONST_APPLICATION)
929 fprintf (out, "APPLICATION,");
930 if (p->type & CONST_EXPLICIT)
931 fprintf (out, "EXPLICIT,");
932 if (p->type & CONST_IMPLICIT)
933 fprintf (out, "IMPLICIT,");
934 if (p->type & CONST_TAG)
935 fprintf (out, "TAG,");
936 if (p->type & CONST_DEFAULT)
937 fprintf (out, "DEFAULT,");
938 if (p->type & CONST_TRUE)
939 fprintf (out, "TRUE,");
940 if (p->type & CONST_FALSE)
941 fprintf (out, "FALSE,");
942 if (p->type & CONST_LIST)
943 fprintf (out, "LIST,");
944 if (p->type & CONST_MIN_MAX)
945 fprintf (out, "MIN_MAX,");
946 if (p->type & CONST_OPTION)
947 fprintf (out, "OPTION,");
948 if (p->type & CONST_1_PARAM)
949 fprintf (out, "1_PARAM,");
950 if (p->type & CONST_SIZE)
951 fprintf (out, "SIZE,");
952 if (p->type & CONST_DEFINED_BY)
953 fprintf (out, "DEF_BY,");
954 if (p->type & CONST_GENERALIZED)
955 fprintf (out, "GENERALIZED,");
956 if (p->type & CONST_UTC)
957 fprintf (out, "UTC,");
958 if (p->type & CONST_SET)
959 fprintf (out, "SET,");
960 if (p->type & CONST_NOT_USED)
961 fprintf (out, "NOT_USED,");
962 if (p->type & CONST_ASSIGN)
963 fprintf (out, "ASSIGNMENT,");
967 if (mode == ASN1_PRINT_ALL)
969 fprintf (out, "\n");
971 else
973 switch (type_field (p->type))
975 case ASN1_ETYPE_CONSTANT:
976 case ASN1_ETYPE_TAG:
977 case ASN1_ETYPE_SIZE:
978 break;
979 default:
980 fprintf (out, "\n");
984 if (p->down)
986 p = p->down;
987 indent += 2;
989 else if (p == root)
991 p = NULL;
992 break;
994 else if (p->right)
995 p = p->right;
996 else
998 while (1)
1000 p = _asn1_find_up (p);
1001 if (p == root)
1003 p = NULL;
1004 break;
1006 indent -= 2;
1007 if (p->right)
1009 p = p->right;
1010 break;
1020 * asn1_number_of_elements:
1021 * @element: pointer to the root of an ASN1 structure.
1022 * @name: the name of a sub-structure of ROOT.
1023 * @num: pointer to an integer where the result will be stored
1025 * Counts the number of elements of a sub-structure called NAME with
1026 * names equal to "?1","?2", ...
1028 * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
1029 * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
1032 asn1_number_of_elements (asn1_node element, const char *name, int *num)
1034 asn1_node node, p;
1036 if (num == NULL)
1037 return ASN1_GENERIC_ERROR;
1039 *num = 0;
1041 node = asn1_find_node (element, name);
1042 if (node == NULL)
1043 return ASN1_ELEMENT_NOT_FOUND;
1045 p = node->down;
1047 while (p)
1049 if (p->name[0] == '?')
1050 (*num)++;
1051 p = p->right;
1054 return ASN1_SUCCESS;
1059 * asn1_find_structure_from_oid:
1060 * @definitions: ASN1 definitions
1061 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1063 * Search the structure that is defined just after an OID definition.
1065 * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1066 * constant string that contains the element name defined just after
1067 * the OID.
1069 const char *
1070 asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
1072 char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
1073 char value[ASN1_MAX_NAME_SIZE];
1074 asn1_node p;
1075 int len;
1076 int result;
1078 if ((definitions == NULL) || (oidValue == NULL))
1079 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1082 strcpy (definitionsName, definitions->name);
1083 strcat (definitionsName, ".");
1085 /* search the OBJECT_ID into definitions */
1086 p = definitions->down;
1087 while (p)
1089 if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
1090 (p->type & CONST_ASSIGN))
1092 strcpy (name, definitionsName);
1093 strcat (name, p->name);
1095 len = ASN1_MAX_NAME_SIZE;
1096 result = asn1_read_value (definitions, name, value, &len);
1098 if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
1100 p = p->right;
1101 if (p == NULL) /* reach the end of ASN1 definitions */
1102 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1104 return p->name;
1107 p = p->right;
1110 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
1114 * asn1_copy_node:
1115 * @dst: Destination asn1_node node.
1116 * @dst_name: Field name in destination node.
1117 * @src: Source asn1_node node.
1118 * @src_name: Field name in source node.
1120 * Create a deep copy of a asn1_node variable.
1122 * Returns: Return %ASN1_SUCCESS on success.
1125 asn1_copy_node (asn1_node dst, const char *dst_name,
1126 asn1_node src, const char *src_name)
1128 /* FIXME: rewrite using copy_structure().
1129 * It seems quite hard to do.
1131 int result;
1132 asn1_node dst_node;
1133 void *data = NULL;
1134 int size = 0;
1136 result = asn1_der_coding (src, src_name, NULL, &size, NULL);
1137 if (result != ASN1_MEM_ERROR)
1138 return result;
1140 data = malloc (size);
1141 if (data == NULL)
1142 return ASN1_MEM_ERROR;
1144 result = asn1_der_coding (src, src_name, data, &size, NULL);
1145 if (result != ASN1_SUCCESS)
1147 free (data);
1148 return result;
1151 dst_node = asn1_find_node (dst, dst_name);
1152 if (dst_node == NULL)
1154 free (data);
1155 return ASN1_ELEMENT_NOT_FOUND;
1158 result = asn1_der_decoding (&dst_node, data, size, NULL);
1160 free (data);
1162 return result;