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