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