Imported Upstream version 4.9
[platform/upstream/libtasn1.git] / lib / structure.c
1 /*
2  * Copyright (C) 2002-2014 Free Software Foundation, Inc.
3  *
4  * This file is part of LIBTASN1.
5  *
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.
10  *
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.
15  *
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
20  */
21
22
23 /*****************************************************/
24 /* File: structure.c                                 */
25 /* Description: Functions to create and delete an    */
26 /*  ASN1 tree.                                       */
27 /*****************************************************/
28
29
30 #include <int.h>
31 #include <structure.h>
32 #include "parser_aux.h"
33 #include <gstr.h>
34
35
36 extern char _asn1_identifierMissing[];
37
38
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)
49 {
50   asn1_node punt;
51
52   punt = calloc (1, sizeof (struct asn1_node_st));
53   if (punt == NULL)
54     return NULL;
55
56   punt->type = type;
57
58   return punt;
59 }
60
61
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)
72 {
73   if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
74     return NULL;
75
76   return node->left;
77 }
78
79
80 int
81 _asn1_create_static_structure (asn1_node pointer, char *output_file_name,
82                                char *vector_name)
83 {
84   FILE *file;
85   asn1_node p;
86   unsigned long t;
87
88   file = fopen (output_file_name, "w");
89
90   if (file == NULL)
91     return ASN1_FILE_NOT_FOUND;
92
93   fprintf (file, "#if HAVE_CONFIG_H\n");
94   fprintf (file, "# include \"config.h\"\n");
95   fprintf (file, "#endif\n\n");
96
97   fprintf (file, "#include <libtasn1.h>\n\n");
98
99   fprintf (file, "const asn1_static_node %s[] = {\n", vector_name);
100
101   p = pointer;
102
103   while (p)
104     {
105       fprintf (file, "  { ");
106
107       if (p->name[0] != 0)
108         fprintf (file, "\"%s\", ", p->name);
109       else
110         fprintf (file, "NULL, ");
111
112       t = p->type;
113       if (p->down)
114         t |= CONST_DOWN;
115       if (p->right)
116         t |= CONST_RIGHT;
117
118       fprintf (file, "%lu, ", t);
119
120       if (p->value)
121         fprintf (file, "\"%s\"},\n", p->value);
122       else
123         fprintf (file, "NULL },\n");
124
125       if (p->down)
126         {
127           p = p->down;
128         }
129       else if (p->right)
130         {
131           p = p->right;
132         }
133       else
134         {
135           while (1)
136             {
137               p = _asn1_find_up (p);
138               if (p == pointer)
139                 {
140                   p = NULL;
141                   break;
142                 }
143               if (p->right)
144                 {
145                   p = p->right;
146                   break;
147                 }
148             }
149         }
150     }
151
152   fprintf (file, "  { NULL, 0, NULL }\n};\n");
153
154   fclose (file);
155
156   return ASN1_SUCCESS;
157 }
158
159
160 /**
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.
166  *
167  * Creates the structures needed to manage the ASN.1 definitions.
168  * @array is a vector created by asn1_parser2array().
169  *
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.
175  **/
176 int
177 asn1_array2tree (const asn1_static_node * array, asn1_node * definitions,
178                  char *errorDescription)
179 {
180   asn1_node p, p_last = NULL;
181   unsigned long k;
182   int move;
183   int result;
184   unsigned int type;
185
186   if (errorDescription)
187     errorDescription[0] = 0;
188
189   if (*definitions != NULL)
190     return ASN1_ELEMENT_NOT_EMPTY;
191
192   move = UP;
193
194   k = 0;
195   while (array[k].value || array[k].type || array[k].name)
196     {
197       type = convert_old_type (array[k].type);
198
199       p = _asn1_add_static_node (type & (~CONST_DOWN));
200       if (array[k].name)
201         _asn1_set_name (p, array[k].name);
202       if (array[k].value)
203         _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
204
205       if (*definitions == NULL)
206         *definitions = p;
207
208       if (move == DOWN)
209         _asn1_set_down (p_last, p);
210       else if (move == RIGHT)
211         _asn1_set_right (p_last, p);
212
213       p_last = p;
214
215       if (type & CONST_DOWN)
216         move = DOWN;
217       else if (type & CONST_RIGHT)
218         move = RIGHT;
219       else
220         {
221           while (1)
222             {
223               if (p_last == *definitions)
224                 break;
225
226               p_last = _asn1_find_up (p_last);
227
228               if (p_last == NULL)
229                 break;
230
231               if (p_last->type & CONST_RIGHT)
232                 {
233                   p_last->type &= ~CONST_RIGHT;
234                   move = RIGHT;
235                   break;
236                 }
237             }                   /* while */
238         }
239       k++;
240     }                           /* while */
241
242   if (p_last == *definitions)
243     {
244       result = _asn1_check_identifier (*definitions);
245       if (result == ASN1_SUCCESS)
246         {
247           _asn1_change_integer_value (*definitions);
248           _asn1_expand_object_id (*definitions);
249         }
250     }
251   else
252     {
253       result = ASN1_ARRAY_ERROR;
254     }
255
256   if (errorDescription != NULL)
257     {
258       if (result == ASN1_IDENTIFIER_NOT_FOUND)
259         {
260           Estrcpy (errorDescription, ":: identifier '");
261           Estrcat (errorDescription, _asn1_identifierMissing);
262           Estrcat (errorDescription, "' not found");
263         }
264       else
265         errorDescription[0] = 0;
266     }
267
268   if (result != ASN1_SUCCESS)
269     {
270       _asn1_delete_list_and_nodes ();
271       *definitions = NULL;
272     }
273   else
274     _asn1_delete_list ();
275
276   return result;
277 }
278
279 /**
280  * asn1_delete_structure:
281  * @structure: pointer to the structure that you want to delete.
282  *
283  * Deletes the structure *@structure.  At the end, *@structure is set
284  * to NULL.
285  *
286  * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
287  *   *@structure was NULL.
288  **/
289 int
290 asn1_delete_structure (asn1_node * structure)
291 {
292   return asn1_delete_structure2(structure, 0);
293 }
294
295 /**
296  * asn1_delete_structure2:
297  * @structure: pointer to the structure that you want to delete.
298  * @flags: additional flags (see %ASN1_DELETE_FLAG)
299  *
300  * Deletes the structure *@structure.  At the end, *@structure is set
301  * to NULL.
302  *
303  * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
304  *   *@structure was NULL.
305  **/
306 int
307 asn1_delete_structure2 (asn1_node * structure, unsigned int flags)
308 {
309   asn1_node p, p2, p3;
310
311   if (*structure == NULL)
312     return ASN1_ELEMENT_NOT_FOUND;
313
314   p = *structure;
315   while (p)
316     {
317       if (p->down)
318         {
319           p = p->down;
320         }
321       else
322         {                       /* no down */
323           p2 = p->right;
324           if (p != *structure)
325             {
326               p3 = _asn1_find_up (p);
327               _asn1_set_down (p3, p2);
328               _asn1_remove_node (p, flags);
329               p = p3;
330             }
331           else
332             {                   /* p==root */
333               p3 = _asn1_find_left (p);
334               if (!p3)
335                 {
336                   p3 = _asn1_find_up (p);
337                   if (p3)
338                     _asn1_set_down (p3, p2);
339                   else
340                     {
341                       if (p->right)
342                         p->right->left = NULL;
343                     }
344                 }
345               else
346                 _asn1_set_right (p3, p2);
347               _asn1_remove_node (p, flags);
348               p = NULL;
349             }
350         }
351     }
352
353   *structure = NULL;
354   return ASN1_SUCCESS;
355 }
356
357
358
359 /**
360  * asn1_delete_element:
361  * @structure: pointer to the structure that contains the element you
362  *   want to delete.
363  * @element_name: element's name you want to delete.
364  *
365  * Deletes the element named *@element_name inside *@structure.
366  *
367  * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
368  *   the @element_name was not found.
369  **/
370 int
371 asn1_delete_element (asn1_node structure, const char *element_name)
372 {
373   asn1_node p2, p3, source_node;
374
375   source_node = asn1_find_node (structure, element_name);
376
377   if (source_node == NULL)
378     return ASN1_ELEMENT_NOT_FOUND;
379
380   p2 = source_node->right;
381   p3 = _asn1_find_left (source_node);
382   if (!p3)
383     {
384       p3 = _asn1_find_up (source_node);
385       if (p3)
386         _asn1_set_down (p3, p2);
387       else if (source_node->right)
388         source_node->right->left = NULL;
389     }
390   else
391     _asn1_set_right (p3, p2);
392
393   return asn1_delete_structure (&source_node);
394 }
395
396 asn1_node
397 _asn1_copy_structure3 (asn1_node source_node)
398 {
399   asn1_node dest_node, p_s, p_d, p_d_prev;
400   int move;
401
402   if (source_node == NULL)
403     return NULL;
404
405   dest_node = _asn1_add_single_node (source_node->type);
406
407   p_s = source_node;
408   p_d = dest_node;
409
410   move = DOWN;
411
412   do
413     {
414       if (move != UP)
415         {
416           if (p_s->name[0] != 0)
417             _asn1_cpy_name (p_d, p_s);
418           if (p_s->value)
419             _asn1_set_value (p_d, p_s->value, p_s->value_len);
420           if (p_s->down)
421             {
422               p_s = p_s->down;
423               p_d_prev = p_d;
424               p_d = _asn1_add_single_node (p_s->type);
425               _asn1_set_down (p_d_prev, p_d);
426               continue;
427             }
428           p_d->start = p_s->start;
429           p_d->end = p_s->end;
430         }
431
432       if (p_s == source_node)
433         break;
434
435       if (p_s->right)
436         {
437           move = RIGHT;
438           p_s = p_s->right;
439           p_d_prev = p_d;
440           p_d = _asn1_add_single_node (p_s->type);
441           _asn1_set_right (p_d_prev, p_d);
442         }
443       else
444         {
445           move = UP;
446           p_s = _asn1_find_up (p_s);
447           p_d = _asn1_find_up (p_d);
448         }
449     }
450   while (p_s != source_node);
451
452   return dest_node;
453 }
454
455
456 static asn1_node
457 _asn1_copy_structure2 (asn1_node root, const char *source_name)
458 {
459   asn1_node source_node;
460
461   source_node = asn1_find_node (root, source_name);
462
463   return _asn1_copy_structure3 (source_node);
464
465 }
466
467
468 static int
469 _asn1_type_choice_config (asn1_node node)
470 {
471   asn1_node p, p2, p3, p4;
472   int move, tlen;
473
474   if (node == NULL)
475     return ASN1_ELEMENT_NOT_FOUND;
476
477   p = node;
478   move = DOWN;
479
480   while (!((p == node) && (move == UP)))
481     {
482       if (move != UP)
483         {
484           if ((type_field (p->type) == ASN1_ETYPE_CHOICE)
485               && (p->type & CONST_TAG))
486             {
487               p2 = p->down;
488               while (p2)
489                 {
490                   if (type_field (p2->type) != ASN1_ETYPE_TAG)
491                     {
492                       p2->type |= CONST_TAG;
493                       p3 = _asn1_find_left (p2);
494                       while (p3)
495                         {
496                           if (type_field (p3->type) == ASN1_ETYPE_TAG)
497                             {
498                               p4 = _asn1_add_single_node (p3->type);
499                               tlen = _asn1_strlen (p3->value);
500                               if (tlen > 0)
501                                 _asn1_set_value (p4, p3->value, tlen + 1);
502                               _asn1_set_right (p4, p2->down);
503                               _asn1_set_down (p2, p4);
504                             }
505                           p3 = _asn1_find_left (p3);
506                         }
507                     }
508                   p2 = p2->right;
509                 }
510               p->type &= ~(CONST_TAG);
511               p2 = p->down;
512               while (p2)
513                 {
514                   p3 = p2->right;
515                   if (type_field (p2->type) == ASN1_ETYPE_TAG)
516                     asn1_delete_structure (&p2);
517                   p2 = p3;
518                 }
519             }
520           move = DOWN;
521         }
522       else
523         move = RIGHT;
524
525       if (move == DOWN)
526         {
527           if (p->down)
528             p = p->down;
529           else
530             move = RIGHT;
531         }
532
533       if (p == node)
534         {
535           move = UP;
536           continue;
537         }
538
539       if (move == RIGHT)
540         {
541           if (p->right)
542             p = p->right;
543           else
544             move = UP;
545         }
546       if (move == UP)
547         p = _asn1_find_up (p);
548     }
549
550   return ASN1_SUCCESS;
551 }
552
553
554 static int
555 _asn1_expand_identifier (asn1_node * node, asn1_node root)
556 {
557   asn1_node p, p2, p3;
558   char name2[ASN1_MAX_NAME_SIZE + 2];
559   int move;
560
561   if (node == NULL)
562     return ASN1_ELEMENT_NOT_FOUND;
563
564   p = *node;
565   move = DOWN;
566
567   while (!((p == *node) && (move == UP)))
568     {
569       if (move != UP)
570         {
571           if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
572             {
573               snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
574               p2 = _asn1_copy_structure2 (root, name2);
575               if (p2 == NULL)
576                 {
577                   return ASN1_IDENTIFIER_NOT_FOUND;
578                 }
579               _asn1_cpy_name (p2, p);
580               p2->right = p->right;
581               p2->left = p->left;
582               if (p->right)
583                 p->right->left = p2;
584               p3 = p->down;
585               if (p3)
586                 {
587                   while (p3->right)
588                     p3 = p3->right;
589                   _asn1_set_right (p3, p2->down);
590                   _asn1_set_down (p2, p->down);
591                 }
592
593               p3 = _asn1_find_left (p);
594               if (p3)
595                 _asn1_set_right (p3, p2);
596               else
597                 {
598                   p3 = _asn1_find_up (p);
599                   if (p3)
600                     _asn1_set_down (p3, p2);
601                   else
602                     {
603                       p2->left = NULL;
604                     }
605                 }
606
607               if (p->type & CONST_SIZE)
608                 p2->type |= CONST_SIZE;
609               if (p->type & CONST_TAG)
610                 p2->type |= CONST_TAG;
611               if (p->type & CONST_OPTION)
612                 p2->type |= CONST_OPTION;
613               if (p->type & CONST_DEFAULT)
614                 p2->type |= CONST_DEFAULT;
615               if (p->type & CONST_SET)
616                 p2->type |= CONST_SET;
617               if (p->type & CONST_NOT_USED)
618                 p2->type |= CONST_NOT_USED;
619
620               if (p == *node)
621                 *node = p2;
622               _asn1_remove_node (p, 0);
623               p = p2;
624               move = DOWN;
625               continue;
626             }
627           move = DOWN;
628         }
629       else
630         move = RIGHT;
631
632       if (move == DOWN)
633         {
634           if (p->down)
635             p = p->down;
636           else
637             move = RIGHT;
638         }
639
640       if (p == *node)
641         {
642           move = UP;
643           continue;
644         }
645
646       if (move == RIGHT)
647         {
648           if (p->right)
649             p = p->right;
650           else
651             move = UP;
652         }
653       if (move == UP)
654         p = _asn1_find_up (p);
655     }
656
657   return ASN1_SUCCESS;
658 }
659
660
661 /**
662  * asn1_create_element:
663  * @definitions: pointer to the structure returned by "parser_asn1" function
664  * @source_name: the name of the type of the new structure (must be
665  *   inside p_structure).
666  * @element: pointer to the structure created.
667  *
668  * Creates a structure of type @source_name.  Example using
669  *  "pkix.asn":
670  *
671  * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
672  *
673  * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
674  *   @source_name is not known.
675  **/
676 int
677 asn1_create_element (asn1_node definitions, const char *source_name,
678                      asn1_node * element)
679 {
680   asn1_node dest_node;
681   int res;
682
683   dest_node = _asn1_copy_structure2 (definitions, source_name);
684
685   if (dest_node == NULL)
686     return ASN1_ELEMENT_NOT_FOUND;
687
688   _asn1_set_name (dest_node, "");
689
690   res = _asn1_expand_identifier (&dest_node, definitions);
691   _asn1_type_choice_config (dest_node);
692
693   *element = dest_node;
694
695   return res;
696 }
697
698
699 /**
700  * asn1_print_structure:
701  * @out: pointer to the output file (e.g. stdout).
702  * @structure: pointer to the structure that you want to visit.
703  * @name: an element of the structure
704  * @mode: specify how much of the structure to print, can be
705  *   %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
706  *   %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
707  *
708  * Prints on the @out file descriptor the structure's tree starting
709  * from the @name element inside the structure @structure.
710  **/
711 void
712 asn1_print_structure (FILE * out, asn1_node structure, const char *name,
713                       int mode)
714 {
715   asn1_node p, root;
716   int k, indent = 0, len, len2, len3;
717
718   if (out == NULL)
719     return;
720
721   root = asn1_find_node (structure, name);
722
723   if (root == NULL)
724     return;
725
726   p = root;
727   while (p)
728     {
729       if (mode == ASN1_PRINT_ALL)
730         {
731           for (k = 0; k < indent; k++)
732             fprintf (out, " ");
733           fprintf (out, "name:");
734           if (p->name[0] != 0)
735             fprintf (out, "%s  ", p->name);
736           else
737             fprintf (out, "NULL  ");
738         }
739       else
740         {
741           switch (type_field (p->type))
742             {
743             case ASN1_ETYPE_CONSTANT:
744             case ASN1_ETYPE_TAG:
745             case ASN1_ETYPE_SIZE:
746               break;
747             default:
748               for (k = 0; k < indent; k++)
749                 fprintf (out, " ");
750               fprintf (out, "name:");
751               if (p->name[0] != 0)
752                 fprintf (out, "%s  ", p->name);
753               else
754                 fprintf (out, "NULL  ");
755             }
756         }
757
758       if (mode != ASN1_PRINT_NAME)
759         {
760           unsigned type = type_field (p->type);
761           switch (type)
762             {
763             case ASN1_ETYPE_CONSTANT:
764               if (mode == ASN1_PRINT_ALL)
765                 fprintf (out, "type:CONST");
766               break;
767             case ASN1_ETYPE_TAG:
768               if (mode == ASN1_PRINT_ALL)
769                 fprintf (out, "type:TAG");
770               break;
771             case ASN1_ETYPE_SIZE:
772               if (mode == ASN1_PRINT_ALL)
773                 fprintf (out, "type:SIZE");
774               break;
775             case ASN1_ETYPE_DEFAULT:
776               fprintf (out, "type:DEFAULT");
777               break;
778             case ASN1_ETYPE_IDENTIFIER:
779               fprintf (out, "type:IDENTIFIER");
780               break;
781             case ASN1_ETYPE_ANY:
782               fprintf (out, "type:ANY");
783               break;
784             case ASN1_ETYPE_CHOICE:
785               fprintf (out, "type:CHOICE");
786               break;
787             case ASN1_ETYPE_DEFINITIONS:
788               fprintf (out, "type:DEFINITIONS");
789               break;
790             CASE_HANDLED_ETYPES:
791               fprintf (out, "%s", _asn1_tags[type].desc);
792               break;
793             default:
794               break;
795             }
796         }
797
798       if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
799         {
800           switch (type_field (p->type))
801             {
802             case ASN1_ETYPE_CONSTANT:
803               if (mode == ASN1_PRINT_ALL)
804                 if (p->value)
805                   fprintf (out, "  value:%s", p->value);
806               break;
807             case ASN1_ETYPE_TAG:
808               if (mode == ASN1_PRINT_ALL)
809                 if (p->value)
810                   fprintf (out, "  value:%s", p->value);
811               break;
812             case ASN1_ETYPE_SIZE:
813               if (mode == ASN1_PRINT_ALL)
814                 if (p->value)
815                   fprintf (out, "  value:%s", p->value);
816               break;
817             case ASN1_ETYPE_DEFAULT:
818               if (p->value)
819                 fprintf (out, "  value:%s", p->value);
820               else if (p->type & CONST_TRUE)
821                 fprintf (out, "  value:TRUE");
822               else if (p->type & CONST_FALSE)
823                 fprintf (out, "  value:FALSE");
824               break;
825             case ASN1_ETYPE_IDENTIFIER:
826               if (p->value)
827                 fprintf (out, "  value:%s", p->value);
828               break;
829             case ASN1_ETYPE_INTEGER:
830               if (p->value)
831                 {
832                   len2 = -1;
833                   len = asn1_get_length_der (p->value, p->value_len, &len2);
834                   fprintf (out, "  value:0x");
835                   if (len > 0)
836                     for (k = 0; k < len; k++)
837                       fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
838                 }
839               break;
840             case ASN1_ETYPE_ENUMERATED:
841               if (p->value)
842                 {
843                   len2 = -1;
844                   len = asn1_get_length_der (p->value, p->value_len, &len2);
845                   fprintf (out, "  value:0x");
846                   if (len > 0)
847                     for (k = 0; k < len; k++)
848                       fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
849                 }
850               break;
851             case ASN1_ETYPE_BOOLEAN:
852               if (p->value)
853                 {
854                   if (p->value[0] == 'T')
855                     fprintf (out, "  value:TRUE");
856                   else if (p->value[0] == 'F')
857                     fprintf (out, "  value:FALSE");
858                 }
859               break;
860             case ASN1_ETYPE_BIT_STRING:
861               if (p->value)
862                 {
863                   len2 = -1;
864                   len = asn1_get_length_der (p->value, p->value_len, &len2);
865                   if (len > 0)
866                     {
867                       fprintf (out, "  value(%i):",
868                                (len - 1) * 8 - (p->value[len2]));
869                       for (k = 1; k < len; k++)
870                         fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
871                     }
872                 }
873               break;
874             case ASN1_ETYPE_GENERALIZED_TIME:
875             case ASN1_ETYPE_UTC_TIME:
876               if (p->value)
877                 {
878                   fprintf (out, "  value:");
879                   for (k = 0; k < p->value_len; k++)
880                     fprintf (out, "%c", (p->value)[k]);
881                 }
882               break;
883             case ASN1_ETYPE_GENERALSTRING:
884             case ASN1_ETYPE_NUMERIC_STRING:
885             case ASN1_ETYPE_IA5_STRING:
886             case ASN1_ETYPE_TELETEX_STRING:
887             case ASN1_ETYPE_PRINTABLE_STRING:
888             case ASN1_ETYPE_UNIVERSAL_STRING:
889             case ASN1_ETYPE_UTF8_STRING:
890             case ASN1_ETYPE_VISIBLE_STRING:
891               if (p->value)
892                 {
893                   len2 = -1;
894                   len = asn1_get_length_der (p->value, p->value_len, &len2);
895                   fprintf (out, "  value:");
896                   if (len > 0)
897                     for (k = 0; k < len; k++)
898                       fprintf (out, "%c", (p->value)[k + len2]);
899                 }
900               break;
901             case ASN1_ETYPE_BMP_STRING:
902             case ASN1_ETYPE_OCTET_STRING:
903               if (p->value)
904                 {
905                   len2 = -1;
906                   len = asn1_get_length_der (p->value, p->value_len, &len2);
907                   fprintf (out, "  value:");
908                   if (len > 0)
909                     for (k = 0; k < len; k++)
910                       fprintf (out, "%02x", (unsigned) (p->value)[k + len2]);
911                 }
912               break;
913             case ASN1_ETYPE_OBJECT_ID:
914               if (p->value)
915                 fprintf (out, "  value:%s", p->value);
916               break;
917             case ASN1_ETYPE_ANY:
918               if (p->value)
919                 {
920                   len3 = -1;
921                   len2 = asn1_get_length_der (p->value, p->value_len, &len3);
922                   fprintf (out, "  value:");
923                   if (len2 > 0)
924                     for (k = 0; k < len2; k++)
925                       fprintf (out, "%02x", (unsigned) (p->value)[k + len3]);
926                 }
927               break;
928             case ASN1_ETYPE_SET:
929             case ASN1_ETYPE_SET_OF:
930             case ASN1_ETYPE_CHOICE:
931             case ASN1_ETYPE_DEFINITIONS:
932             case ASN1_ETYPE_SEQUENCE_OF:
933             case ASN1_ETYPE_SEQUENCE:
934             case ASN1_ETYPE_NULL:
935               break;
936             default:
937               break;
938             }
939         }
940
941       if (mode == ASN1_PRINT_ALL)
942         {
943           if (p->type & 0x1FFFFF00)
944             {
945               fprintf (out, "  attr:");
946               if (p->type & CONST_UNIVERSAL)
947                 fprintf (out, "UNIVERSAL,");
948               if (p->type & CONST_PRIVATE)
949                 fprintf (out, "PRIVATE,");
950               if (p->type & CONST_APPLICATION)
951                 fprintf (out, "APPLICATION,");
952               if (p->type & CONST_EXPLICIT)
953                 fprintf (out, "EXPLICIT,");
954               if (p->type & CONST_IMPLICIT)
955                 fprintf (out, "IMPLICIT,");
956               if (p->type & CONST_TAG)
957                 fprintf (out, "TAG,");
958               if (p->type & CONST_DEFAULT)
959                 fprintf (out, "DEFAULT,");
960               if (p->type & CONST_TRUE)
961                 fprintf (out, "TRUE,");
962               if (p->type & CONST_FALSE)
963                 fprintf (out, "FALSE,");
964               if (p->type & CONST_LIST)
965                 fprintf (out, "LIST,");
966               if (p->type & CONST_MIN_MAX)
967                 fprintf (out, "MIN_MAX,");
968               if (p->type & CONST_OPTION)
969                 fprintf (out, "OPTION,");
970               if (p->type & CONST_1_PARAM)
971                 fprintf (out, "1_PARAM,");
972               if (p->type & CONST_SIZE)
973                 fprintf (out, "SIZE,");
974               if (p->type & CONST_DEFINED_BY)
975                 fprintf (out, "DEF_BY,");
976               if (p->type & CONST_GENERALIZED)
977                 fprintf (out, "GENERALIZED,");
978               if (p->type & CONST_UTC)
979                 fprintf (out, "UTC,");
980               if (p->type & CONST_SET)
981                 fprintf (out, "SET,");
982               if (p->type & CONST_NOT_USED)
983                 fprintf (out, "NOT_USED,");
984               if (p->type & CONST_ASSIGN)
985                 fprintf (out, "ASSIGNMENT,");
986             }
987         }
988
989       if (mode == ASN1_PRINT_ALL)
990         {
991           fprintf (out, "\n");
992         }
993       else
994         {
995           switch (type_field (p->type))
996             {
997             case ASN1_ETYPE_CONSTANT:
998             case ASN1_ETYPE_TAG:
999             case ASN1_ETYPE_SIZE:
1000               break;
1001             default:
1002               fprintf (out, "\n");
1003             }
1004         }
1005
1006       if (p->down)
1007         {
1008           p = p->down;
1009           indent += 2;
1010         }
1011       else if (p == root)
1012         {
1013           p = NULL;
1014           break;
1015         }
1016       else if (p->right)
1017         p = p->right;
1018       else
1019         {
1020           while (1)
1021             {
1022               p = _asn1_find_up (p);
1023               if (p == root)
1024                 {
1025                   p = NULL;
1026                   break;
1027                 }
1028               indent -= 2;
1029               if (p->right)
1030                 {
1031                   p = p->right;
1032                   break;
1033                 }
1034             }
1035         }
1036     }
1037 }
1038
1039
1040
1041 /**
1042  * asn1_number_of_elements:
1043  * @element: pointer to the root of an ASN1 structure.
1044  * @name: the name of a sub-structure of ROOT.
1045  * @num: pointer to an integer where the result will be stored
1046  *
1047  * Counts the number of elements of a sub-structure called NAME with
1048  * names equal to "?1","?2", ...
1049  *
1050  * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
1051  *   @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
1052  **/
1053 int
1054 asn1_number_of_elements (asn1_node element, const char *name, int *num)
1055 {
1056   asn1_node node, p;
1057
1058   if (num == NULL)
1059     return ASN1_GENERIC_ERROR;
1060
1061   *num = 0;
1062
1063   node = asn1_find_node (element, name);
1064   if (node == NULL)
1065     return ASN1_ELEMENT_NOT_FOUND;
1066
1067   p = node->down;
1068
1069   while (p)
1070     {
1071       if (p->name[0] == '?')
1072         (*num)++;
1073       p = p->right;
1074     }
1075
1076   return ASN1_SUCCESS;
1077 }
1078
1079
1080 /**
1081  * asn1_find_structure_from_oid:
1082  * @definitions: ASN1 definitions
1083  * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1084  *
1085  * Search the structure that is defined just after an OID definition.
1086  *
1087  * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1088  *   constant string that contains the element name defined just after
1089  *   the OID.
1090  **/
1091 const char *
1092 asn1_find_structure_from_oid (asn1_node definitions, const char *oidValue)
1093 {
1094   char name[2 * ASN1_MAX_NAME_SIZE + 1];
1095   char value[ASN1_MAX_NAME_SIZE];
1096   asn1_node p;
1097   int len;
1098   int result;
1099   const char *definitionsName;
1100
1101   if ((definitions == NULL) || (oidValue == NULL))
1102     return NULL;                /* ASN1_ELEMENT_NOT_FOUND; */
1103
1104   definitionsName = definitions->name;
1105
1106   /* search the OBJECT_ID into definitions */
1107   p = definitions->down;
1108   while (p)
1109     {
1110       if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
1111           (p->type & CONST_ASSIGN))
1112         {
1113           snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name);
1114
1115           len = ASN1_MAX_NAME_SIZE;
1116           result = asn1_read_value (definitions, name, value, &len);
1117
1118           if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
1119             {
1120               p = p->right;
1121               if (p == NULL)    /* reach the end of ASN1 definitions */
1122                 return NULL;    /* ASN1_ELEMENT_NOT_FOUND; */
1123
1124               return p->name;
1125             }
1126         }
1127       p = p->right;
1128     }
1129
1130   return NULL;                  /* ASN1_ELEMENT_NOT_FOUND; */
1131 }
1132
1133 /**
1134  * asn1_copy_node:
1135  * @dst: Destination asn1 node.
1136  * @dst_name: Field name in destination node.
1137  * @src: Source asn1 node.
1138  * @src_name: Field name in source node.
1139  *
1140  * Create a deep copy of a asn1_node variable. That
1141  * function requires @dst to be expanded using asn1_create_element().
1142  *
1143  * Returns: Return %ASN1_SUCCESS on success.
1144  **/
1145 int
1146 asn1_copy_node (asn1_node dst, const char *dst_name,
1147                 asn1_node src, const char *src_name)
1148 {
1149   int result;
1150   asn1_node dst_node;
1151   void *data = NULL;
1152   int size = 0;
1153
1154   result = asn1_der_coding (src, src_name, NULL, &size, NULL);
1155   if (result != ASN1_MEM_ERROR)
1156     return result;
1157
1158   data = malloc (size);
1159   if (data == NULL)
1160     return ASN1_MEM_ERROR;
1161
1162   result = asn1_der_coding (src, src_name, data, &size, NULL);
1163   if (result != ASN1_SUCCESS)
1164     {
1165       free (data);
1166       return result;
1167     }
1168
1169   dst_node = asn1_find_node (dst, dst_name);
1170   if (dst_node == NULL)
1171     {
1172       free (data);
1173       return ASN1_ELEMENT_NOT_FOUND;
1174     }
1175
1176   result = asn1_der_decoding (&dst_node, data, size, NULL);
1177
1178   free (data);
1179
1180   return result;
1181 }
1182
1183 /**
1184  * asn1_dup_node:
1185  * @src: Source asn1 node.
1186  * @src_name: Field name in source node.
1187  *
1188  * Create a deep copy of a asn1_node variable. This function
1189  * will return an exact copy of the provided structure.
1190  *
1191  * Returns: Return %NULL on failure.
1192  **/
1193 asn1_node
1194 asn1_dup_node (asn1_node src, const char *src_name)
1195 {
1196   return _asn1_copy_structure2(src, src_name);
1197 }