Initialize Tizen 2.3
[external/libtasn1.git] / lib / structure.c
1 /*
2  * Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009, 2010 Free
3  * Software Foundation, Inc.
4  *
5  * This file is part of LIBTASN1.
6  *
7  * The LIBTASN1 library is free software; you can redistribute it
8  * and/or modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA
21  */
22
23
24 /*****************************************************/
25 /* File: structure.c                                 */
26 /* Description: Functions to create and delete an    */
27 /*  ASN1 tree.                                       */
28 /*****************************************************/
29
30
31 #include <int.h>
32 #include <structure.h>
33 #include "parser_aux.h"
34 #include <gstr.h>
35
36
37 extern char _asn1_identifierMissing[];
38
39
40 /******************************************************/
41 /* Function : _asn1_add_node_only                     */
42 /* Description: creates a new NODE_ASN element.       */
43 /* Parameters:                                        */
44 /*   type: type of the new element (see TYPE_         */
45 /*         and CONST_ constants).                     */
46 /* Return: pointer to the new element.                */
47 /******************************************************/
48 ASN1_TYPE
49 _asn1_add_node_only (unsigned int type)
50 {
51   ASN1_TYPE punt;
52
53   punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
54   if (punt == NULL)
55     return NULL;
56
57   punt->type = type;
58
59   return punt;
60 }
61
62
63 /******************************************************************/
64 /* Function : _asn1_find_left                                     */
65 /* Description: returns the NODE_ASN element with RIGHT field that*/
66 /*              points the element NODE.                          */
67 /* Parameters:                                                    */
68 /*   node: NODE_ASN element pointer.                              */
69 /* Return: NULL if not found.                                     */
70 /******************************************************************/
71 ASN1_TYPE
72 _asn1_find_left (ASN1_TYPE node)
73 {
74   if ((node == NULL) || (node->left == NULL) || (node->left->down == node))
75     return NULL;
76
77   return node->left;
78 }
79
80
81 asn1_retCode
82 _asn1_create_static_structure (ASN1_TYPE pointer, char *output_file_name,
83                                char *vector_name)
84 {
85   FILE *file;
86   ASN1_TYPE p;
87   unsigned long t;
88
89   file = fopen (output_file_name, "w");
90
91   if (file == NULL)
92     return ASN1_FILE_NOT_FOUND;
93
94   fprintf (file, "#if HAVE_CONFIG_H\n");
95   fprintf (file, "# include \"config.h\"\n");
96   fprintf (file, "#endif\n\n");
97
98   fprintf (file, "#include <libtasn1.h>\n\n");
99
100   fprintf (file, "const ASN1_ARRAY_TYPE %s[] = {\n", vector_name);
101
102   p = pointer;
103
104   while (p)
105     {
106       fprintf (file, "  { ");
107
108       if (p->name)
109         fprintf (file, "\"%s\", ", p->name);
110       else
111         fprintf (file, "NULL, ");
112
113       t = p->type;
114       if (p->down)
115         t |= CONST_DOWN;
116       if (p->right)
117         t |= CONST_RIGHT;
118
119       fprintf (file, "%lu, ", t);
120
121       if (p->value)
122         fprintf (file, "\"%s\"},\n", p->value);
123       else
124         fprintf (file, "NULL },\n");
125
126       if (p->down)
127         {
128           p = p->down;
129         }
130       else if (p->right)
131         {
132           p = p->right;
133         }
134       else
135         {
136           while (1)
137             {
138               p = _asn1_find_up (p);
139               if (p == pointer)
140                 {
141                   p = NULL;
142                   break;
143                 }
144               if (p->right)
145                 {
146                   p = p->right;
147                   break;
148                 }
149             }
150         }
151     }
152
153   fprintf (file, "  { NULL, 0, NULL }\n};\n");
154
155   fclose (file);
156
157   return ASN1_SUCCESS;
158 }
159
160
161 /**
162  * asn1_array2tree:
163  * @array: specify the array that contains ASN.1 declarations
164  * @definitions: return the pointer to the structure created by
165  *   *ARRAY ASN.1 declarations
166  * @errorDescription: return the error description.
167  *
168  * Creates the structures needed to manage the ASN.1 definitions.
169  * @array is a vector created by asn1_parser2array().
170  *
171  * Returns:
172  *
173  * %ASN1_SUCCESS: Structure created correctly.
174  *
175  * %ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
176  *
177  * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
178  *   is not defined (see @errorDescription for more information).
179  *
180  * %ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
181  **/
182 asn1_retCode
183 asn1_array2tree (const ASN1_ARRAY_TYPE * array, ASN1_TYPE * definitions,
184                  char *errorDescription)
185 {
186   ASN1_TYPE p, p_last = NULL;
187   unsigned long k;
188   int move;
189   asn1_retCode result;
190
191
192   if (*definitions != ASN1_TYPE_EMPTY)
193     return ASN1_ELEMENT_NOT_EMPTY;
194
195   move = UP;
196
197   k = 0;
198   while (array[k].value || array[k].type || array[k].name)
199     {
200       p = _asn1_add_node (array[k].type & (~CONST_DOWN));
201       if (array[k].name)
202         _asn1_set_name (p, array[k].name);
203       if (array[k].value)
204         _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1);
205
206       if (*definitions == NULL)
207         *definitions = p;
208
209       if (move == DOWN)
210         _asn1_set_down (p_last, p);
211       else if (move == RIGHT)
212         _asn1_set_right (p_last, p);
213
214       p_last = p;
215
216       if (array[k].type & CONST_DOWN)
217         move = DOWN;
218       else if (array[k].type & CONST_RIGHT)
219         move = RIGHT;
220       else
221         {
222           while (1)
223             {
224               if (p_last == *definitions)
225                 break;
226
227               p_last = _asn1_find_up (p_last);
228
229               if (p_last == NULL)
230                 break;
231
232               if (p_last->type & CONST_RIGHT)
233                 {
234                   p_last->type &= ~CONST_RIGHT;
235                   move = RIGHT;
236                   break;
237                 }
238             }                   /* while */
239         }
240       k++;
241     }                           /* while */
242
243   if (p_last == *definitions)
244     {
245       result = _asn1_check_identifier (*definitions);
246       if (result == ASN1_SUCCESS)
247         {
248           _asn1_change_integer_value (*definitions);
249           _asn1_expand_object_id (*definitions);
250         }
251     }
252   else
253     {
254       result = ASN1_ARRAY_ERROR;
255     }
256
257   if (errorDescription != NULL)
258     {
259       if (result == ASN1_IDENTIFIER_NOT_FOUND)
260         {
261           Estrcpy (errorDescription, ":: identifier '");
262           Estrcat (errorDescription, _asn1_identifierMissing);
263           Estrcat (errorDescription, "' not found");
264         }
265       else
266         errorDescription[0] = 0;
267     }
268
269   if (result != ASN1_SUCCESS)
270     {
271       _asn1_delete_list_and_nodes ();
272       *definitions = ASN1_TYPE_EMPTY;
273     }
274   else
275     _asn1_delete_list ();
276
277   return result;
278 }
279
280 /**
281  * asn1_delete_structure:
282  * @structure: pointer to the structure that you want to delete.
283  *
284  * Deletes the structure *@structure.  At the end, *@structure is set
285  * to ASN1_TYPE_EMPTY.
286  *
287  * Returns:
288  *
289  * %ASN1_SUCCESS: Everything OK.
290  *
291  * %ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
292  **/
293 asn1_retCode
294 asn1_delete_structure (ASN1_TYPE * structure)
295 {
296   ASN1_TYPE p, p2, p3;
297
298   if (*structure == ASN1_TYPE_EMPTY)
299     return ASN1_ELEMENT_NOT_FOUND;
300
301   p = *structure;
302   while (p)
303     {
304       if (p->down)
305         {
306           p = p->down;
307         }
308       else
309         {                       /* no down */
310           p2 = p->right;
311           if (p != *structure)
312             {
313               p3 = _asn1_find_up (p);
314               _asn1_set_down (p3, p2);
315               _asn1_remove_node (p);
316               p = p3;
317             }
318           else
319             {                   /* p==root */
320               p3 = _asn1_find_left (p);
321               if (!p3)
322                 {
323                   p3 = _asn1_find_up (p);
324                   if (p3)
325                     _asn1_set_down (p3, p2);
326                   else
327                     {
328                       if (p->right)
329                         p->right->left = NULL;
330                     }
331                 }
332               else
333                 _asn1_set_right (p3, p2);
334               _asn1_remove_node (p);
335               p = NULL;
336             }
337         }
338     }
339
340   *structure = ASN1_TYPE_EMPTY;
341   return ASN1_SUCCESS;
342 }
343
344
345
346 /**
347  * asn1_delete_element:
348  * @structure: pointer to the structure that contains the element you
349  *   want to delete.
350  * @element_name: element's name you want to delete.
351  *
352  * Deletes the element named *@element_name inside *@structure.
353  *
354  * Returns:
355  *
356  * %ASN1_SUCCESS: Everything OK.
357  *
358  * %ASN1_ELEMENT_NOT_FOUND: The name element was not found.
359  **/
360 asn1_retCode
361 asn1_delete_element (ASN1_TYPE structure, const char *element_name)
362 {
363   ASN1_TYPE p2, p3, source_node;
364
365   source_node = asn1_find_node (structure, element_name);
366
367   if (source_node == ASN1_TYPE_EMPTY)
368     return ASN1_ELEMENT_NOT_FOUND;
369
370   p2 = source_node->right;
371   p3 = _asn1_find_left (source_node);
372   if (!p3)
373     {
374       p3 = _asn1_find_up (source_node);
375       if (p3)
376         _asn1_set_down (p3, p2);
377       else if (source_node->right)
378         source_node->right->left = NULL;
379     }
380   else
381     _asn1_set_right (p3, p2);
382
383   return asn1_delete_structure (&source_node);
384 }
385
386 ASN1_TYPE
387 _asn1_copy_structure3 (ASN1_TYPE source_node)
388 {
389   ASN1_TYPE dest_node, p_s, p_d, p_d_prev;
390   int move;
391
392   if (source_node == NULL)
393     return NULL;
394
395   dest_node = _asn1_add_node_only (source_node->type);
396
397   p_s = source_node;
398   p_d = dest_node;
399
400   move = DOWN;
401
402   do
403     {
404       if (move != UP)
405         {
406           if (p_s->name)
407             _asn1_set_name (p_d, p_s->name);
408           if (p_s->value)
409             _asn1_set_value (p_d, p_s->value, p_s->value_len);
410           move = DOWN;
411         }
412       else
413         move = RIGHT;
414
415       if (move == DOWN)
416         {
417           if (p_s->down)
418             {
419               p_s = p_s->down;
420               p_d_prev = p_d;
421               p_d = _asn1_add_node_only (p_s->type);
422               _asn1_set_down (p_d_prev, p_d);
423             }
424           else
425             move = RIGHT;
426         }
427
428       if (p_s == source_node)
429         break;
430
431       if (move == RIGHT)
432         {
433           if (p_s->right)
434             {
435               p_s = p_s->right;
436               p_d_prev = p_d;
437               p_d = _asn1_add_node_only (p_s->type);
438               _asn1_set_right (p_d_prev, p_d);
439             }
440           else
441             move = UP;
442         }
443       if (move == UP)
444         {
445           p_s = _asn1_find_up (p_s);
446           p_d = _asn1_find_up (p_d);
447         }
448     }
449   while (p_s != source_node);
450
451   return dest_node;
452 }
453
454
455 static ASN1_TYPE
456 _asn1_copy_structure2 (ASN1_TYPE root, const char *source_name)
457 {
458   ASN1_TYPE source_node;
459
460   source_node = asn1_find_node (root, source_name);
461
462   return _asn1_copy_structure3 (source_node);
463
464 }
465
466
467 static asn1_retCode
468 _asn1_type_choice_config (ASN1_TYPE node)
469 {
470   ASN1_TYPE p, p2, p3, p4;
471   int move, tlen;
472
473   if (node == NULL)
474     return ASN1_ELEMENT_NOT_FOUND;
475
476   p = node;
477   move = DOWN;
478
479   while (!((p == node) && (move == UP)))
480     {
481       if (move != UP)
482         {
483           if ((type_field (p->type) == TYPE_CHOICE) && (p->type & CONST_TAG))
484             {
485               p2 = p->down;
486               while (p2)
487                 {
488                   if (type_field (p2->type) != TYPE_TAG)
489                     {
490                       p2->type |= CONST_TAG;
491                       p3 = _asn1_find_left (p2);
492                       while (p3)
493                         {
494                           if (type_field (p3->type) == TYPE_TAG)
495                             {
496                               p4 = _asn1_add_node_only (p3->type);
497                               tlen = strlen (p3->value);
498                               if (tlen > 0)
499                                 _asn1_set_value (p4, p3->value, tlen + 1);
500                               _asn1_set_right (p4, p2->down);
501                               _asn1_set_down (p2, p4);
502                             }
503                           p3 = _asn1_find_left (p3);
504                         }
505                     }
506                   p2 = p2->right;
507                 }
508               p->type &= ~(CONST_TAG);
509               p2 = p->down;
510               while (p2)
511                 {
512                   p3 = p2->right;
513                   if (type_field (p2->type) == TYPE_TAG)
514                     asn1_delete_structure (&p2);
515                   p2 = p3;
516                 }
517             }
518           move = DOWN;
519         }
520       else
521         move = RIGHT;
522
523       if (move == DOWN)
524         {
525           if (p->down)
526             p = p->down;
527           else
528             move = RIGHT;
529         }
530
531       if (p == node)
532         {
533           move = UP;
534           continue;
535         }
536
537       if (move == RIGHT)
538         {
539           if (p->right)
540             p = p->right;
541           else
542             move = UP;
543         }
544       if (move == UP)
545         p = _asn1_find_up (p);
546     }
547
548   return ASN1_SUCCESS;
549 }
550
551
552 static asn1_retCode
553 _asn1_expand_identifier (ASN1_TYPE * node, ASN1_TYPE root)
554 {
555   ASN1_TYPE p, p2, p3;
556   char name2[ASN1_MAX_NAME_SIZE + 2];
557   int move;
558
559   if (node == NULL)
560     return ASN1_ELEMENT_NOT_FOUND;
561
562   p = *node;
563   move = DOWN;
564
565   while (!((p == *node) && (move == UP)))
566     {
567       if (move != UP)
568         {
569           if (type_field (p->type) == TYPE_IDENTIFIER)
570             {
571               _asn1_str_cpy (name2, sizeof (name2), root->name);
572               _asn1_str_cat (name2, sizeof (name2), ".");
573               _asn1_str_cat (name2, sizeof (name2), p->value);
574               p2 = _asn1_copy_structure2 (root, name2);
575               if (p2 == NULL)
576                 {
577                   return ASN1_IDENTIFIER_NOT_FOUND;
578                 }
579               _asn1_set_name (p2, p->name);
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);
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:
674  *
675  * %ASN1_SUCCESS: Creation OK.
676  *
677  * %ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
678  **/
679 asn1_retCode
680 asn1_create_element (ASN1_TYPE definitions, const char *source_name,
681                      ASN1_TYPE * element)
682 {
683   ASN1_TYPE dest_node;
684   int res;
685
686   dest_node = _asn1_copy_structure2 (definitions, source_name);
687
688   if (dest_node == NULL)
689     return ASN1_ELEMENT_NOT_FOUND;
690
691   _asn1_set_name (dest_node, "");
692
693   res = _asn1_expand_identifier (&dest_node, definitions);
694   _asn1_type_choice_config (dest_node);
695
696   *element = dest_node;
697
698   return res;
699 }
700
701
702 /**
703  * asn1_print_structure:
704  * @out: pointer to the output file (e.g. stdout).
705  * @structure: pointer to the structure that you want to visit.
706  * @name: an element of the structure
707  * @mode: specify how much of the structure to print, can be
708  *   %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
709  *   %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
710  *
711  * Prints on the @out file descriptor the structure's tree starting
712  * from the @name element inside the structure @structure.
713  **/
714 void
715 asn1_print_structure (FILE * out, ASN1_TYPE structure, const char *name,
716                       int mode)
717 {
718   ASN1_TYPE p, root;
719   int k, indent = 0, len, len2, len3;
720
721   if (out == NULL)
722     return;
723
724   root = asn1_find_node (structure, name);
725
726   if (root == NULL)
727     return;
728
729   p = root;
730   while (p)
731     {
732       if (mode == ASN1_PRINT_ALL)
733         {
734           for (k = 0; k < indent; k++)
735             fprintf (out, " ");
736           fprintf (out, "name:");
737           if (p->name)
738             fprintf (out, "%s  ", p->name);
739           else
740             fprintf (out, "NULL  ");
741         }
742       else
743         {
744           switch (type_field (p->type))
745             {
746             case TYPE_CONSTANT:
747             case TYPE_TAG:
748             case TYPE_SIZE:
749               break;
750             default:
751               for (k = 0; k < indent; k++)
752                 fprintf (out, " ");
753               fprintf (out, "name:");
754               if (p->name)
755                 fprintf (out, "%s  ", p->name);
756               else
757                 fprintf (out, "NULL  ");
758             }
759         }
760
761       if (mode != ASN1_PRINT_NAME)
762         {
763           switch (type_field (p->type))
764             {
765             case TYPE_CONSTANT:
766               if (mode == ASN1_PRINT_ALL)
767                 fprintf (out, "type:CONST");
768               break;
769             case TYPE_TAG:
770               if (mode == ASN1_PRINT_ALL)
771                 fprintf (out, "type:TAG");
772               break;
773             case TYPE_SIZE:
774               if (mode == ASN1_PRINT_ALL)
775                 fprintf (out, "type:SIZE");
776               break;
777             case TYPE_DEFAULT:
778               fprintf (out, "type:DEFAULT");
779               break;
780             case TYPE_NULL:
781               fprintf (out, "type:NULL");
782               break;
783             case TYPE_IDENTIFIER:
784               fprintf (out, "type:IDENTIFIER");
785               break;
786             case TYPE_INTEGER:
787               fprintf (out, "type:INTEGER");
788               break;
789             case TYPE_ENUMERATED:
790               fprintf (out, "type:ENUMERATED");
791               break;
792             case TYPE_TIME:
793               fprintf (out, "type:TIME");
794               break;
795             case TYPE_BOOLEAN:
796               fprintf (out, "type:BOOLEAN");
797               break;
798             case TYPE_SEQUENCE:
799               fprintf (out, "type:SEQUENCE");
800               break;
801             case TYPE_BIT_STRING:
802               fprintf (out, "type:BIT_STR");
803               break;
804             case TYPE_OCTET_STRING:
805               fprintf (out, "type:OCT_STR");
806               break;
807             case TYPE_GENERALSTRING:
808               fprintf (out, "type:GENERALSTRING");
809               break;
810             case TYPE_SEQUENCE_OF:
811               fprintf (out, "type:SEQ_OF");
812               break;
813             case TYPE_OBJECT_ID:
814               fprintf (out, "type:OBJ_ID");
815               break;
816             case TYPE_ANY:
817               fprintf (out, "type:ANY");
818               break;
819             case TYPE_SET:
820               fprintf (out, "type:SET");
821               break;
822             case TYPE_SET_OF:
823               fprintf (out, "type:SET_OF");
824               break;
825             case TYPE_CHOICE:
826               fprintf (out, "type:CHOICE");
827               break;
828             case TYPE_DEFINITIONS:
829               fprintf (out, "type:DEFINITIONS");
830               break;
831             default:
832               break;
833             }
834         }
835
836       if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL))
837         {
838           switch (type_field (p->type))
839             {
840             case TYPE_CONSTANT:
841               if (mode == ASN1_PRINT_ALL)
842                 if (p->value)
843                   fprintf (out, "  value:%s", p->value);
844               break;
845             case TYPE_TAG:
846               if (mode == ASN1_PRINT_ALL)
847                 if (p->value)
848                   fprintf (out, "  value:%s", p->value);
849               break;
850             case TYPE_SIZE:
851               if (mode == ASN1_PRINT_ALL)
852                 if (p->value)
853                   fprintf (out, "  value:%s", p->value);
854               break;
855             case TYPE_DEFAULT:
856               if (p->value)
857                 fprintf (out, "  value:%s", p->value);
858               else if (p->type & CONST_TRUE)
859                 fprintf (out, "  value:TRUE");
860               else if (p->type & CONST_FALSE)
861                 fprintf (out, "  value:FALSE");
862               break;
863             case TYPE_IDENTIFIER:
864               if (p->value)
865                 fprintf (out, "  value:%s", p->value);
866               break;
867             case TYPE_INTEGER:
868               if (p->value)
869                 {
870                   len2 = -1;
871                   len = asn1_get_length_der (p->value, p->value_len, &len2);
872                   fprintf (out, "  value:0x");
873                   if (len > 0)
874                     for (k = 0; k < len; k++)
875                       fprintf (out, "%02x", (p->value)[k + len2]);
876                 }
877               break;
878             case TYPE_ENUMERATED:
879               if (p->value)
880                 {
881                   len2 = -1;
882                   len = asn1_get_length_der (p->value, p->value_len, &len2);
883                   fprintf (out, "  value:0x");
884                   if (len > 0)
885                     for (k = 0; k < len; k++)
886                       fprintf (out, "%02x", (p->value)[k + len2]);
887                 }
888               break;
889             case TYPE_TIME:
890               if (p->value)
891                 fprintf (out, "  value:%s", p->value);
892               break;
893             case TYPE_BOOLEAN:
894               if (p->value)
895                 {
896                   if (p->value[0] == 'T')
897                     fprintf (out, "  value:TRUE");
898                   else if (p->value[0] == 'F')
899                     fprintf (out, "  value:FALSE");
900                 }
901               break;
902             case TYPE_BIT_STRING:
903               if (p->value)
904                 {
905                   len2 = -1;
906                   len = asn1_get_length_der (p->value, p->value_len, &len2);
907                   if (len > 0)
908                     {
909                       fprintf (out, "  value(%i):",
910                                (len - 1) * 8 - (p->value[len2]));
911                       for (k = 1; k < len; k++)
912                         fprintf (out, "%02x", (p->value)[k + len2]);
913                     }
914                 }
915               break;
916             case TYPE_OCTET_STRING:
917               if (p->value)
918                 {
919                   len2 = -1;
920                   len = asn1_get_length_der (p->value, p->value_len, &len2);
921                   fprintf (out, "  value:");
922                   if (len > 0)
923                     for (k = 0; k < len; k++)
924                       fprintf (out, "%02x", (p->value)[k + len2]);
925                 }
926               break;
927             case TYPE_GENERALSTRING:
928               if (p->value)
929                 {
930                   len2 = -1;
931                   len = asn1_get_length_der (p->value, p->value_len, &len2);
932                   fprintf (out, "  value:");
933                   if (len > 0)
934                     for (k = 0; k < len; k++)
935                       fprintf (out, "%02x", (p->value)[k + len2]);
936                 }
937               break;
938             case TYPE_OBJECT_ID:
939               if (p->value)
940                 fprintf (out, "  value:%s", p->value);
941               break;
942             case TYPE_ANY:
943               if (p->value)
944                 {
945                   len3 = -1;
946                   len2 = asn1_get_length_der (p->value, p->value_len, &len3);
947                   fprintf (out, "  value:");
948                   if (len2 > 0)
949                     for (k = 0; k < len2; k++)
950                       fprintf (out, "%02x", (p->value)[k + len3]);
951                 }
952               break;
953             case TYPE_SET:
954             case TYPE_SET_OF:
955             case TYPE_CHOICE:
956             case TYPE_DEFINITIONS:
957             case TYPE_SEQUENCE_OF:
958             case TYPE_SEQUENCE:
959             case TYPE_NULL:
960               break;
961             default:
962               break;
963             }
964         }
965
966       if (mode == ASN1_PRINT_ALL)
967         {
968           if (p->type & 0x1FFFFF00)
969             {
970               fprintf (out, "  attr:");
971               if (p->type & CONST_UNIVERSAL)
972                 fprintf (out, "UNIVERSAL,");
973               if (p->type & CONST_PRIVATE)
974                 fprintf (out, "PRIVATE,");
975               if (p->type & CONST_APPLICATION)
976                 fprintf (out, "APPLICATION,");
977               if (p->type & CONST_EXPLICIT)
978                 fprintf (out, "EXPLICIT,");
979               if (p->type & CONST_IMPLICIT)
980                 fprintf (out, "IMPLICIT,");
981               if (p->type & CONST_TAG)
982                 fprintf (out, "TAG,");
983               if (p->type & CONST_DEFAULT)
984                 fprintf (out, "DEFAULT,");
985               if (p->type & CONST_TRUE)
986                 fprintf (out, "TRUE,");
987               if (p->type & CONST_FALSE)
988                 fprintf (out, "FALSE,");
989               if (p->type & CONST_LIST)
990                 fprintf (out, "LIST,");
991               if (p->type & CONST_MIN_MAX)
992                 fprintf (out, "MIN_MAX,");
993               if (p->type & CONST_OPTION)
994                 fprintf (out, "OPTION,");
995               if (p->type & CONST_1_PARAM)
996                 fprintf (out, "1_PARAM,");
997               if (p->type & CONST_SIZE)
998                 fprintf (out, "SIZE,");
999               if (p->type & CONST_DEFINED_BY)
1000                 fprintf (out, "DEF_BY,");
1001               if (p->type & CONST_GENERALIZED)
1002                 fprintf (out, "GENERALIZED,");
1003               if (p->type & CONST_UTC)
1004                 fprintf (out, "UTC,");
1005               if (p->type & CONST_SET)
1006                 fprintf (out, "SET,");
1007               if (p->type & CONST_NOT_USED)
1008                 fprintf (out, "NOT_USED,");
1009               if (p->type & CONST_ASSIGN)
1010                 fprintf (out, "ASSIGNMENT,");
1011             }
1012         }
1013
1014       if (mode == ASN1_PRINT_ALL)
1015         {
1016           fprintf (out, "\n");
1017         }
1018       else
1019         {
1020           switch (type_field (p->type))
1021             {
1022             case TYPE_CONSTANT:
1023             case TYPE_TAG:
1024             case TYPE_SIZE:
1025               break;
1026             default:
1027               fprintf (out, "\n");
1028             }
1029         }
1030
1031       if (p->down)
1032         {
1033           p = p->down;
1034           indent += 2;
1035         }
1036       else if (p == root)
1037         {
1038           p = NULL;
1039           break;
1040         }
1041       else if (p->right)
1042         p = p->right;
1043       else
1044         {
1045           while (1)
1046             {
1047               p = _asn1_find_up (p);
1048               if (p == root)
1049                 {
1050                   p = NULL;
1051                   break;
1052                 }
1053               indent -= 2;
1054               if (p->right)
1055                 {
1056                   p = p->right;
1057                   break;
1058                 }
1059             }
1060         }
1061     }
1062 }
1063
1064
1065
1066 /**
1067  * asn1_number_of_elements:
1068  * @element: pointer to the root of an ASN1 structure.
1069  * @name: the name of a sub-structure of ROOT.
1070  * @num: pointer to an integer where the result will be stored
1071  *
1072  * Counts the number of elements of a sub-structure called NAME with
1073  * names equal to "?1","?2", ...
1074  *
1075  * Returns:
1076  *
1077  *  %ASN1_SUCCESS: Creation OK.
1078  *
1079  *  %ASN1_ELEMENT_NOT_FOUND: NAME isn't known.
1080  *
1081  *  %ASN1_GENERIC_ERROR: Pointer num equal to NULL.
1082  **/
1083 asn1_retCode
1084 asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num)
1085 {
1086   ASN1_TYPE node, p;
1087
1088   if (num == NULL)
1089     return ASN1_GENERIC_ERROR;
1090
1091   *num = 0;
1092
1093   node = asn1_find_node (element, name);
1094   if (node == NULL)
1095     return ASN1_ELEMENT_NOT_FOUND;
1096
1097   p = node->down;
1098
1099   while (p)
1100     {
1101       if ((p->name) && (p->name[0] == '?'))
1102         (*num)++;
1103       p = p->right;
1104     }
1105
1106   return ASN1_SUCCESS;
1107 }
1108
1109
1110 /**
1111  * asn1_find_structure_from_oid:
1112  * @definitions: ASN1 definitions
1113  * @oidValue: value of the OID to search (e.g. "1.2.3.4").
1114  *
1115  * Search the structure that is defined just after an OID definition.
1116  *
1117  * Returns: %NULL when @oidValue not found, otherwise the pointer to a
1118  *   constant string that contains the element name defined just after
1119  *   the OID.
1120  **/
1121 const char *
1122 asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue)
1123 {
1124   char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
1125   char value[ASN1_MAX_NAME_SIZE];
1126   ASN1_TYPE p;
1127   int len;
1128   asn1_retCode result;
1129
1130   if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL))
1131     return NULL;                /* ASN1_ELEMENT_NOT_FOUND; */
1132
1133
1134   strcpy (definitionsName, definitions->name);
1135   strcat (definitionsName, ".");
1136
1137   /* search the OBJECT_ID into definitions */
1138   p = definitions->down;
1139   while (p)
1140     {
1141       if ((type_field (p->type) == TYPE_OBJECT_ID) &&
1142           (p->type & CONST_ASSIGN))
1143         {
1144           strcpy (name, definitionsName);
1145           strcat (name, p->name);
1146
1147           len = ASN1_MAX_NAME_SIZE;
1148           result = asn1_read_value (definitions, name, value, &len);
1149
1150           if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value)))
1151             {
1152               p = p->right;
1153               if (p == NULL)    /* reach the end of ASN1 definitions */
1154                 return NULL;    /* ASN1_ELEMENT_NOT_FOUND; */
1155
1156               return p->name;
1157             }
1158         }
1159       p = p->right;
1160     }
1161
1162   return NULL;                  /* ASN1_ELEMENT_NOT_FOUND; */
1163 }
1164
1165 /**
1166  * asn1_copy_node:
1167  * @dst: Destination ASN1_TYPE node.
1168  * @dst_name: Field name in destination node.
1169  * @src: Source ASN1_TYPE node.
1170  * @src_name: Field name in source node.
1171  *
1172  * Create a deep copy of a ASN1_TYPE variable.
1173  *
1174  * Return value: Return %ASN1_SUCCESS on success.
1175  **/
1176 asn1_retCode
1177 asn1_copy_node (ASN1_TYPE dst, const char *dst_name,
1178                 ASN1_TYPE src, const char *src_name)
1179 {
1180 /* FIXME: rewrite using copy_structure().
1181  * It seems quite hard to do.
1182  */
1183   int result;
1184   ASN1_TYPE dst_node;
1185   void *data = NULL;
1186   int size = 0;
1187
1188   result = asn1_der_coding (src, src_name, NULL, &size, NULL);
1189   if (result != ASN1_MEM_ERROR)
1190     return result;
1191
1192   data = _asn1_malloc (size);
1193   if (data == NULL)
1194     return ASN1_MEM_ERROR;
1195
1196   result = asn1_der_coding (src, src_name, data, &size, NULL);
1197   if (result != ASN1_SUCCESS)
1198     {
1199       _asn1_free (data);
1200       return result;
1201     }
1202
1203   dst_node = asn1_find_node (dst, dst_name);
1204   if (dst_node == NULL)
1205     {
1206       _asn1_free (data);
1207       return ASN1_ELEMENT_NOT_FOUND;
1208     }
1209
1210   result = asn1_der_decoding (&dst_node, data, size, NULL);
1211
1212   _asn1_free (data);
1213
1214   return result;
1215 }