effedb23661a9bc4c5d90677f9915ddd2d2b0636
[platform/upstream/libtasn1.git] / lib / parser_aux.c
1 /*
2  * Copyright (C) 2000-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 #include <int.h>
23 #include <hash-pjw-bare.h>
24 #include "parser_aux.h"
25 #include "gstr.h"
26 #include "structure.h"
27 #include "element.h"
28
29 char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1];   /* identifier name not found */
30
31 /***********************************************/
32 /* Type: list_type                             */
33 /* Description: type used in the list during   */
34 /* the structure creation.                     */
35 /***********************************************/
36 typedef struct list_struct
37 {
38   asn1_node node;
39   struct list_struct *next;
40 } list_type;
41
42
43 /* Pointer to the first element of the list */
44 list_type *firstElement = NULL;
45
46 /******************************************************/
47 /* Function : _asn1_add_static_node                   */
48 /* Description: creates a new NODE_ASN element and    */
49 /* puts it in the list pointed by firstElement.       */
50 /* Parameters:                                        */
51 /*   type: type of the new element (see ASN1_ETYPE_   */
52 /*         and CONST_ constants).                     */
53 /* Return: pointer to the new element.                */
54 /******************************************************/
55 asn1_node
56 _asn1_add_static_node (unsigned int type)
57 {
58   list_type *listElement;
59   asn1_node punt;
60
61   punt = calloc (1, sizeof (struct asn1_node_st));
62   if (punt == NULL)
63     return NULL;
64
65   listElement = malloc (sizeof (list_type));
66   if (listElement == NULL)
67     {
68       free (punt);
69       return NULL;
70     }
71
72   listElement->node = punt;
73   listElement->next = firstElement;
74   firstElement = listElement;
75
76   punt->type = type;
77
78   return punt;
79 }
80
81 /**
82  * asn1_find_node:
83  * @pointer: NODE_ASN element pointer.
84  * @name: null terminated string with the element's name to find.
85  *
86  * Searches for an element called @name starting from @pointer.  The
87  * name is composed by differents identifiers separated by dots.  When
88  * *@pointer has a name, the first identifier must be the name of
89  * *@pointer, otherwise it must be the name of one child of *@pointer.
90  *
91  * Returns: the search result, or %NULL if not found.
92  **/
93 asn1_node
94 asn1_find_node (asn1_node pointer, const char *name)
95 {
96   asn1_node p;
97   char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
98   const char *n_start;
99   unsigned int nsize;
100   unsigned int nhash;
101
102   if (pointer == NULL)
103     return NULL;
104
105   if (name == NULL)
106     return NULL;
107
108   p = pointer;
109   n_start = name;
110
111   if (p->name[0] != 0)
112     {                           /* has *pointer got a name ? */
113       n_end = strchr (n_start, '.');    /* search the first dot */
114       if (n_end)
115         {
116           nsize = n_end - n_start;
117           memcpy (n, n_start, nsize);
118           n[nsize] = 0;
119           n_start = n_end;
120           n_start++;
121
122           nhash = hash_pjw_bare (n, nsize);
123         }
124       else
125         {
126           nsize = _asn1_str_cpy (n, sizeof (n), n_start);
127           nhash = hash_pjw_bare (n, nsize);
128
129           n_start = NULL;
130         }
131
132       while (p)
133         {
134           if (nhash == p->name_hash && (!strcmp (p->name, n)))
135             break;
136           else
137             p = p->right;
138         }                       /* while */
139
140       if (p == NULL)
141         return NULL;
142     }
143   else
144     {                           /* *pointer doesn't have a name */
145       if (n_start[0] == 0)
146         return p;
147     }
148
149   while (n_start)
150     {                           /* Has the end of NAME been reached? */
151       n_end = strchr (n_start, '.');    /* search the next dot */
152       if (n_end)
153         {
154           nsize = n_end - n_start;
155           memcpy (n, n_start, nsize);
156           n[nsize] = 0;
157           n_start = n_end;
158           n_start++;
159
160           nhash = hash_pjw_bare (n, nsize);
161         }
162       else
163         {
164           nsize = _asn1_str_cpy (n, sizeof (n), n_start);
165           nhash = hash_pjw_bare (n, nsize);
166           n_start = NULL;
167         }
168
169       if (p->down == NULL)
170         return NULL;
171
172       p = p->down;
173
174       /* The identifier "?LAST" indicates the last element
175          in the right chain. */
176       if (!strcmp (n, "?LAST"))
177         {
178           if (p == NULL)
179             return NULL;
180           while (p->right)
181             p = p->right;
182         }
183       else
184         {                       /* no "?LAST" */
185           while (p)
186             {
187               if (p->name_hash == nhash && !strcmp (p->name, n))
188                 break;
189               else
190                 p = p->right;
191             }
192           if (p == NULL)
193             return NULL;
194         }
195     }                           /* while */
196
197   return p;
198 }
199
200
201 /******************************************************************/
202 /* Function : _asn1_set_value                                     */
203 /* Description: sets the field VALUE in a NODE_ASN element. The   */
204 /*              previous value (if exist) will be lost            */
205 /* Parameters:                                                    */
206 /*   node: element pointer.                                       */
207 /*   value: pointer to the value that you want to set.            */
208 /*   len: character number of value.                              */
209 /* Return: pointer to the NODE_ASN element.                       */
210 /******************************************************************/
211 asn1_node
212 _asn1_set_value (asn1_node node, const void *value, unsigned int len)
213 {
214   if (node == NULL)
215     return node;
216   if (node->value)
217     {
218       if (node->value != node->small_value)
219         free (node->value);
220       node->value = NULL;
221       node->value_len = 0;
222     }
223
224   if (!len)
225     return node;
226
227   if (len < sizeof (node->small_value))
228     {
229       node->value = node->small_value;
230     }
231   else
232     {
233       node->value = malloc (len);
234       if (node->value == NULL)
235         return NULL;
236     }
237   node->value_len = len;
238
239   memcpy (node->value, value, len);
240   return node;
241 }
242
243 /******************************************************************/
244 /* Function : _asn1_set_value_lv                                  */
245 /* Description: sets the field VALUE in a NODE_ASN element. The   */
246 /*              previous value (if exist) will be lost. The value */
247 /*              given is stored as an length-value format (LV     */
248 /* Parameters:                                                    */
249 /*   node: element pointer.                                       */
250 /*   value: pointer to the value that you want to set.            */
251 /*   len: character number of value.                              */
252 /* Return: pointer to the NODE_ASN element.                       */
253 /******************************************************************/
254 asn1_node
255 _asn1_set_value_lv (asn1_node node, const void *value, unsigned int len)
256 {
257   int len2;
258   void *temp;
259
260   if (node == NULL)
261     return node;
262
263   asn1_length_der (len, NULL, &len2);
264   temp = malloc (len + len2);
265   if (temp == NULL)
266     return NULL;
267
268   asn1_octet_der (value, len, temp, &len2);
269   return _asn1_set_value_m (node, temp, len2);
270 }
271
272 /* the same as _asn1_set_value except that it sets an already malloc'ed
273  * value.
274  */
275 asn1_node
276 _asn1_set_value_m (asn1_node node, void *value, unsigned int len)
277 {
278   if (node == NULL)
279     return node;
280
281   if (node->value)
282     {
283       if (node->value != node->small_value)
284         free (node->value);
285       node->value = NULL;
286       node->value_len = 0;
287     }
288
289   if (!len)
290     return node;
291
292   node->value = value;
293   node->value_len = len;
294
295   return node;
296 }
297
298 /******************************************************************/
299 /* Function : _asn1_append_value                                  */
300 /* Description: appends to the field VALUE in a NODE_ASN element. */
301 /*                                                                */
302 /* Parameters:                                                    */
303 /*   node: element pointer.                                       */
304 /*   value: pointer to the value that you want to be appended.    */
305 /*   len: character number of value.                              */
306 /* Return: pointer to the NODE_ASN element.                       */
307 /******************************************************************/
308 asn1_node
309 _asn1_append_value (asn1_node node, const void *value, unsigned int len)
310 {
311   if (node == NULL)
312     return node;
313   if (node->value != NULL && node->value != node->small_value)
314     {
315       /* value is allocated */
316       int prev_len = node->value_len;
317       node->value_len += len;
318       node->value = realloc (node->value, node->value_len);
319       if (node->value == NULL)
320         {
321           node->value_len = 0;
322           return NULL;
323         }
324       memcpy (&node->value[prev_len], value, len);
325
326       return node;
327     }
328   else if (node->value == node->small_value)
329     {
330       /* value is in node */
331       int prev_len = node->value_len;
332       node->value_len += len;
333       node->value = malloc (node->value_len);
334       if (node->value == NULL)
335         {
336           node->value_len = 0;
337           return NULL;
338         }
339       memcpy (node->value, node->small_value, prev_len);
340       memcpy (&node->value[prev_len], value, len);
341
342       return node;
343     }
344   else                          /* node->value == NULL */
345     return _asn1_set_value (node, value, len);
346 }
347
348 /******************************************************************/
349 /* Function : _asn1_set_name                                      */
350 /* Description: sets the field NAME in a NODE_ASN element. The    */
351 /*              previous value (if exist) will be lost            */
352 /* Parameters:                                                    */
353 /*   node: element pointer.                                       */
354 /*   name: a null terminated string with the name that you want   */
355 /*         to set.                                                */
356 /* Return: pointer to the NODE_ASN element.                       */
357 /******************************************************************/
358 asn1_node
359 _asn1_set_name (asn1_node node, const char *name)
360 {
361   unsigned int nsize;
362
363   if (node == NULL)
364     return node;
365
366   if (name == NULL)
367     {
368       node->name[0] = 0;
369       node->name_hash = hash_pjw_bare (node->name, 0);
370       return node;
371     }
372
373   nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
374   node->name_hash = hash_pjw_bare (node->name, nsize);
375
376   return node;
377 }
378
379 /******************************************************************/
380 /* Function : _asn1_cpy_name                                      */
381 /* Description: copies the field NAME in a NODE_ASN element.      */
382 /* Parameters:                                                    */
383 /*   dst: a dest element pointer.                                 */
384 /*   src: a source element pointer.                               */
385 /* Return: pointer to the NODE_ASN element.                       */
386 /******************************************************************/
387 asn1_node
388 _asn1_cpy_name (asn1_node dst, asn1_node src)
389 {
390   if (dst == NULL)
391     return dst;
392
393   if (src == NULL)
394     {
395       dst->name[0] = 0;
396       dst->name_hash = hash_pjw_bare (dst->name, 0);
397       return dst;
398     }
399
400   _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
401   dst->name_hash = src->name_hash;
402
403   return dst;
404 }
405
406 /******************************************************************/
407 /* Function : _asn1_set_right                                     */
408 /* Description: sets the field RIGHT in a NODE_ASN element.       */
409 /* Parameters:                                                    */
410 /*   node: element pointer.                                       */
411 /*   right: pointer to a NODE_ASN element that you want be pointed*/
412 /*          by NODE.                                              */
413 /* Return: pointer to *NODE.                                      */
414 /******************************************************************/
415 asn1_node
416 _asn1_set_right (asn1_node node, asn1_node right)
417 {
418   if (node == NULL)
419     return node;
420   node->right = right;
421   if (right)
422     right->left = node;
423   return node;
424 }
425
426
427 /******************************************************************/
428 /* Function : _asn1_get_last_right                                */
429 /* Description: return the last element along the right chain.    */
430 /* Parameters:                                                    */
431 /*   node: starting element pointer.                              */
432 /* Return: pointer to the last element along the right chain.     */
433 /******************************************************************/
434 asn1_node
435 _asn1_get_last_right (asn1_node node)
436 {
437   asn1_node p;
438
439   if (node == NULL)
440     return NULL;
441   p = node;
442   while (p->right)
443     p = p->right;
444   return p;
445 }
446
447 /******************************************************************/
448 /* Function : _asn1_remove_node                                   */
449 /* Description: gets free the memory allocated for an NODE_ASN    */
450 /*              element (not the elements pointed by it).         */
451 /* Parameters:                                                    */
452 /*   node: NODE_ASN element pointer.                              */
453 /*   flags: ASN1_DELETE_FLAG_*                                    */
454 /******************************************************************/
455 void
456 _asn1_remove_node (asn1_node node, unsigned int flags)
457 {
458   if (node == NULL)
459     return;
460
461   if (node->value != NULL)
462     {
463       if (flags & ASN1_DELETE_FLAG_ZEROIZE)
464         {
465           safe_memset(node->value, 0, node->value_len);
466         }
467
468       if (node->value != node->small_value)
469         free (node->value);
470     }
471   free (node);
472 }
473
474 /******************************************************************/
475 /* Function : _asn1_find_up                                       */
476 /* Description: return the father of the NODE_ASN element.        */
477 /* Parameters:                                                    */
478 /*   node: NODE_ASN element pointer.                              */
479 /* Return: Null if not found.                                     */
480 /******************************************************************/
481 asn1_node
482 _asn1_find_up (asn1_node node)
483 {
484   asn1_node p;
485
486   if (node == NULL)
487     return NULL;
488
489   p = node;
490
491   while ((p->left != NULL) && (p->left->right == p))
492     p = p->left;
493
494   return p->left;
495 }
496
497 /******************************************************************/
498 /* Function : _asn1_delete_list                                   */
499 /* Description: deletes the list elements (not the elements       */
500 /*  pointed by them).                                             */
501 /******************************************************************/
502 void
503 _asn1_delete_list (void)
504 {
505   list_type *listElement;
506
507   while (firstElement)
508     {
509       listElement = firstElement;
510       firstElement = firstElement->next;
511       free (listElement);
512     }
513 }
514
515 /******************************************************************/
516 /* Function : _asn1_delete_list_and nodes                         */
517 /* Description: deletes the list elements and the elements        */
518 /*  pointed by them.                                              */
519 /******************************************************************/
520 void
521 _asn1_delete_list_and_nodes (void)
522 {
523   list_type *listElement;
524
525   while (firstElement)
526     {
527       listElement = firstElement;
528       firstElement = firstElement->next;
529       _asn1_remove_node (listElement->node, 0);
530       free (listElement);
531     }
532 }
533
534
535 char *
536 _asn1_ltostr (long v, char *str)
537 {
538   long d, r;
539   char temp[LTOSTR_MAX_SIZE];
540   int count, k, start;
541
542   if (v < 0)
543     {
544       str[0] = '-';
545       start = 1;
546       v = -v;
547     }
548   else
549     start = 0;
550
551   count = 0;
552   do
553     {
554       d = v / 10;
555       r = v - d * 10;
556       temp[start + count] = '0' + (char) r;
557       count++;
558       v = d;
559     }
560   while (v);
561
562   for (k = 0; k < count; k++)
563     str[k + start] = temp[start + count - k - 1];
564   str[count + start] = 0;
565   return str;
566 }
567
568
569 /******************************************************************/
570 /* Function : _asn1_change_integer_value                          */
571 /* Description: converts into DER coding the value assign to an   */
572 /*   INTEGER constant.                                            */
573 /* Parameters:                                                    */
574 /*   node: root of an ASN1element.                                */
575 /* Return:                                                        */
576 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
577 /*   otherwise ASN1_SUCCESS                                             */
578 /******************************************************************/
579 int
580 _asn1_change_integer_value (asn1_node node)
581 {
582   asn1_node p;
583   unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
584   unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1];
585   int len;
586
587   if (node == NULL)
588     return ASN1_ELEMENT_NOT_FOUND;
589
590   p = node;
591   while (p)
592     {
593       if ((type_field (p->type) == ASN1_ETYPE_INTEGER)
594           && (p->type & CONST_ASSIGN))
595         {
596           if (p->value)
597             {
598               _asn1_convert_integer (p->value, val, sizeof (val), &len);
599               asn1_octet_der (val, len, val2, &len);
600               _asn1_set_value (p, val2, len);
601             }
602         }
603
604       if (p->down)
605         {
606           p = p->down;
607         }
608       else
609         {
610           if (p == node)
611             p = NULL;
612           else if (p->right)
613             p = p->right;
614           else
615             {
616               while (1)
617                 {
618                   p = _asn1_find_up (p);
619                   if (p == node)
620                     {
621                       p = NULL;
622                       break;
623                     }
624                   if (p->right)
625                     {
626                       p = p->right;
627                       break;
628                     }
629                 }
630             }
631         }
632     }
633
634   return ASN1_SUCCESS;
635 }
636
637
638 /******************************************************************/
639 /* Function : _asn1_expand_object_id                              */
640 /* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
641 /* Parameters:                                                    */
642 /*   node: root of an ASN1 element.                               */
643 /* Return:                                                        */
644 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
645 /*   otherwise ASN1_SUCCESS                                             */
646 /******************************************************************/
647 int
648 _asn1_expand_object_id (asn1_node node)
649 {
650   asn1_node p, p2, p3, p4, p5;
651   char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1];
652   int move, tlen;
653
654   if (node == NULL)
655     return ASN1_ELEMENT_NOT_FOUND;
656
657   _asn1_str_cpy (name_root, sizeof (name_root), node->name);
658
659   p = node;
660   move = DOWN;
661
662   while (!((p == node) && (move == UP)))
663     {
664       if (move != UP)
665         {
666           if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID)
667               && (p->type & CONST_ASSIGN))
668             {
669               p2 = p->down;
670               if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
671                 {
672                   if (p2->value && !isdigit (p2->value[0]))
673                     {
674                       _asn1_str_cpy (name2, sizeof (name2), name_root);
675                       _asn1_str_cat (name2, sizeof (name2), ".");
676                       _asn1_str_cat (name2, sizeof (name2),
677                                      (char *) p2->value);
678                       p3 = asn1_find_node (node, name2);
679                       if (!p3
680                           || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
681                           || !(p3->type & CONST_ASSIGN))
682                         return ASN1_ELEMENT_NOT_FOUND;
683                       _asn1_set_down (p, p2->right);
684                       _asn1_remove_node (p2, 0);
685                       p2 = p;
686                       p4 = p3->down;
687                       while (p4)
688                         {
689                           if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
690                             {
691                               p5 =
692                                 _asn1_add_single_node (ASN1_ETYPE_CONSTANT);
693                               _asn1_set_name (p5, p4->name);
694                               tlen = _asn1_strlen (p4->value);
695                               if (tlen > 0)
696                                 _asn1_set_value (p5, p4->value, tlen + 1);
697                               if (p2 == p)
698                                 {
699                                   _asn1_set_right (p5, p->down);
700                                   _asn1_set_down (p, p5);
701                                 }
702                               else
703                                 {
704                                   _asn1_set_right (p5, p2->right);
705                                   _asn1_set_right (p2, p5);
706                                 }
707                               p2 = p5;
708                             }
709                           p4 = p4->right;
710                         }
711                       move = DOWN;
712                       continue;
713                     }
714                 }
715             }
716           move = DOWN;
717         }
718       else
719         move = RIGHT;
720
721       if (move == DOWN)
722         {
723           if (p->down)
724             p = p->down;
725           else
726             move = RIGHT;
727         }
728
729       if (p == node)
730         {
731           move = UP;
732           continue;
733         }
734
735       if (move == RIGHT)
736         {
737           if (p->right)
738             p = p->right;
739           else
740             move = UP;
741         }
742       if (move == UP)
743         p = _asn1_find_up (p);
744     }
745
746
747   /*******************************/
748   /*       expand DEFAULT        */
749   /*******************************/
750   p = node;
751   move = DOWN;
752
753   while (!((p == node) && (move == UP)))
754     {
755       if (move != UP)
756         {
757           if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
758               (p->type & CONST_DEFAULT))
759             {
760               p2 = p->down;
761               if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
762                 {
763                   _asn1_str_cpy (name2, sizeof (name2), name_root);
764                   _asn1_str_cat (name2, sizeof (name2), ".");
765                   _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
766                   p3 = asn1_find_node (node, name2);
767                   if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID)
768                       || !(p3->type & CONST_ASSIGN))
769                     return ASN1_ELEMENT_NOT_FOUND;
770                   p4 = p3->down;
771                   name2[0] = 0;
772                   while (p4)
773                     {
774                       if (type_field (p4->type) == ASN1_ETYPE_CONSTANT)
775                         {
776                           if (name2[0])
777                             _asn1_str_cat (name2, sizeof (name2), ".");
778                           _asn1_str_cat (name2, sizeof (name2),
779                                          (char *) p4->value);
780                         }
781                       p4 = p4->right;
782                     }
783                   tlen = strlen (name2);
784                   if (tlen > 0)
785                     _asn1_set_value (p2, name2, tlen + 1);
786                 }
787             }
788           move = DOWN;
789         }
790       else
791         move = RIGHT;
792
793       if (move == DOWN)
794         {
795           if (p->down)
796             p = p->down;
797           else
798             move = RIGHT;
799         }
800
801       if (p == node)
802         {
803           move = UP;
804           continue;
805         }
806
807       if (move == RIGHT)
808         {
809           if (p->right)
810             p = p->right;
811           else
812             move = UP;
813         }
814       if (move == UP)
815         p = _asn1_find_up (p);
816     }
817
818   return ASN1_SUCCESS;
819 }
820
821
822 /******************************************************************/
823 /* Function : _asn1_type_set_config                               */
824 /* Description: sets the CONST_SET and CONST_NOT_USED properties  */
825 /*   in the fields of the SET elements.                           */
826 /* Parameters:                                                    */
827 /*   node: root of an ASN1 element.                               */
828 /* Return:                                                        */
829 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
830 /*   otherwise ASN1_SUCCESS                                             */
831 /******************************************************************/
832 int
833 _asn1_type_set_config (asn1_node node)
834 {
835   asn1_node p, p2;
836   int move;
837
838   if (node == NULL)
839     return ASN1_ELEMENT_NOT_FOUND;
840
841   p = node;
842   move = DOWN;
843
844   while (!((p == node) && (move == UP)))
845     {
846       if (move != UP)
847         {
848           if (type_field (p->type) == ASN1_ETYPE_SET)
849             {
850               p2 = p->down;
851               while (p2)
852                 {
853                   if (type_field (p2->type) != ASN1_ETYPE_TAG)
854                     p2->type |= CONST_SET | CONST_NOT_USED;
855                   p2 = p2->right;
856                 }
857             }
858           move = DOWN;
859         }
860       else
861         move = RIGHT;
862
863       if (move == DOWN)
864         {
865           if (p->down)
866             p = p->down;
867           else
868             move = RIGHT;
869         }
870
871       if (p == node)
872         {
873           move = UP;
874           continue;
875         }
876
877       if (move == RIGHT)
878         {
879           if (p->right)
880             p = p->right;
881           else
882             move = UP;
883         }
884       if (move == UP)
885         p = _asn1_find_up (p);
886     }
887
888   return ASN1_SUCCESS;
889 }
890
891
892 /******************************************************************/
893 /* Function : _asn1_check_identifier                              */
894 /* Description: checks the definitions of all the identifiers     */
895 /*   and the first element of an OBJECT_ID (e.g. {pkix 0 4}).     */
896 /*   The _asn1_identifierMissing global variable is filled if     */
897 /*   necessary.                                                   */
898 /* Parameters:                                                    */
899 /*   node: root of an ASN1 element.                               */
900 /* Return:                                                        */
901 /*   ASN1_ELEMENT_NOT_FOUND      if NODE is NULL,                 */
902 /*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
903 /*   otherwise ASN1_SUCCESS                                       */
904 /******************************************************************/
905 int
906 _asn1_check_identifier (asn1_node node)
907 {
908   asn1_node p, p2;
909   char name2[ASN1_MAX_NAME_SIZE * 2 + 2];
910
911   if (node == NULL)
912     return ASN1_ELEMENT_NOT_FOUND;
913
914   p = node;
915   while (p)
916     {
917       if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER)
918         {
919           _asn1_str_cpy (name2, sizeof (name2), node->name);
920           _asn1_str_cat (name2, sizeof (name2), ".");
921           _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
922           p2 = asn1_find_node (node, name2);
923           if (p2 == NULL)
924             {
925               if (p->value)
926                 _asn1_strcpy (_asn1_identifierMissing, p->value);
927               else
928                 _asn1_strcpy (_asn1_identifierMissing, "(null)");
929               return ASN1_IDENTIFIER_NOT_FOUND;
930             }
931         }
932       else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
933                (p->type & CONST_DEFAULT))
934         {
935           p2 = p->down;
936           if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT))
937             {
938               _asn1_str_cpy (name2, sizeof (name2), node->name);
939               _asn1_str_cat (name2, sizeof (name2), ".");
940               _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
941               _asn1_strcpy (_asn1_identifierMissing, p2->value);
942               p2 = asn1_find_node (node, name2);
943               if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) ||
944                   !(p2->type & CONST_ASSIGN))
945                 return ASN1_IDENTIFIER_NOT_FOUND;
946               else
947                 _asn1_identifierMissing[0] = 0;
948             }
949         }
950       else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) &&
951                (p->type & CONST_ASSIGN))
952         {
953           p2 = p->down;
954           if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT))
955             {
956               if (p2->value && !isdigit (p2->value[0]))
957                 {
958                   _asn1_str_cpy (name2, sizeof (name2), node->name);
959                   _asn1_str_cat (name2, sizeof (name2), ".");
960                   _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
961                   _asn1_strcpy (_asn1_identifierMissing, p2->value);
962                   p2 = asn1_find_node (node, name2);
963                   if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID)
964                       || !(p2->type & CONST_ASSIGN))
965                     return ASN1_IDENTIFIER_NOT_FOUND;
966                   else
967                     _asn1_identifierMissing[0] = 0;
968                 }
969             }
970         }
971
972       if (p->down)
973         {
974           p = p->down;
975         }
976       else if (p->right)
977         p = p->right;
978       else
979         {
980           while (1)
981             {
982               p = _asn1_find_up (p);
983               if (p == node)
984                 {
985                   p = NULL;
986                   break;
987                 }
988               if (p->right)
989                 {
990                   p = p->right;
991                   break;
992                 }
993             }
994         }
995     }
996
997   return ASN1_SUCCESS;
998 }
999
1000
1001 /******************************************************************/
1002 /* Function : _asn1_set_default_tag                               */
1003 /* Description: sets the default IMPLICIT or EXPLICIT property in */
1004 /*   the tagged elements that don't have this declaration.        */
1005 /* Parameters:                                                    */
1006 /*   node: pointer to a DEFINITIONS element.                      */
1007 /* Return:                                                        */
1008 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to   */
1009 /*     a DEFINITIONS element,                                     */
1010 /*   otherwise ASN1_SUCCESS                                       */
1011 /******************************************************************/
1012 int
1013 _asn1_set_default_tag (asn1_node node)
1014 {
1015   asn1_node p;
1016
1017   if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS))
1018     return ASN1_ELEMENT_NOT_FOUND;
1019
1020   p = node;
1021   while (p)
1022     {
1023       if ((type_field (p->type) == ASN1_ETYPE_TAG) &&
1024           !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT))
1025         {
1026           if (node->type & CONST_EXPLICIT)
1027             p->type |= CONST_EXPLICIT;
1028           else
1029             p->type |= CONST_IMPLICIT;
1030         }
1031
1032       if (p->down)
1033         {
1034           p = p->down;
1035         }
1036       else if (p->right)
1037         p = p->right;
1038       else
1039         {
1040           while (1)
1041             {
1042               p = _asn1_find_up (p);
1043               if (p == node)
1044                 {
1045                   p = NULL;
1046                   break;
1047                 }
1048               if (p->right)
1049                 {
1050                   p = p->right;
1051                   break;
1052                 }
1053             }
1054         }
1055     }
1056
1057   return ASN1_SUCCESS;
1058 }