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