change asn1_create_element interface
[platform/upstream/libtasn1.git] / lib / parser_aux.c
1 /*
2  *      Copyright (C) 2000,2001 Fabio Fiorina
3  *
4  * This file is part of LIBASN1.
5  *
6  * The LIBTASN1 library is free software; you can redistribute it and/or
7  * 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,
12  * but 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20
21 #include <int.h>
22 #include <errors.h>
23 #include "parser_aux.h"
24 #include "der.h"
25 #include "gstr.h"
26 #include "structure.h"
27 #include "element.h"
28
29 char _asn1_identifierMissing[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   node_asn           *node;
38   struct list_struct *next;
39 } list_type;
40
41
42 /* Pointer to the first element of the list */
43 list_type *firstElement=NULL;
44
45 /******************************************************/
46 /* Function : _asn1_add_node                          */
47 /* Description: creates a new NODE_ASN element and    */
48 /* puts it in the list pointed by firstElement.       */
49 /* Parameters:                                        */
50 /*   type: type of the new element (see TYPE_         */
51 /*         and CONST_ constants).                     */
52 /* Return: pointer to the new element.                */
53 /******************************************************/
54 node_asn *
55 _asn1_add_node(unsigned int type)
56 {
57   list_type *listElement;
58   node_asn *punt;
59
60   punt=(node_asn *) _asn1_malloc(sizeof(node_asn));
61   if (punt==NULL) return NULL;
62   
63   listElement=(list_type *) _asn1_malloc(sizeof(list_type));
64   if(listElement==NULL){
65     _asn1_free(punt);
66     return NULL;
67   }
68
69   listElement->node=punt;
70   listElement->next=firstElement;
71   firstElement=listElement;
72
73   punt->left=NULL;
74   punt->name=NULL;
75   punt->type=type; 
76   punt->value=NULL;
77   punt->down=NULL;
78   punt->right=NULL; 
79
80   return punt;
81 }
82
83 /******************************************************************/
84 /* Function : _asn1_find_mode                                     */
85 /* Description: searches an element called NAME starting from     */
86 /*              POINTER. The name is composed by differents       */
87 /*              identifiers separated by dots.When *POINTER has a */
88 /*              name, the first identifier must be the name of    */
89 /*              *POINTER, otherwise it must be the name of one    */
90 /*              child of *POINTER.                                */
91 /* Parameters:                                                    */
92 /*   pointer: NODE_ASN element pointer.                           */
93 /*   name: null terminated string with the element's name to find.*/
94 /* Return: the searching result. NULL if not find.                */
95 /******************************************************************/
96 node_asn *
97 _asn1_find_node(node_asn *pointer,const char *name)
98 {
99   node_asn *p;
100   char *n_end,n[MAX_NAME_SIZE+1];
101   const char *n_start;
102
103   if(pointer == NULL) return NULL;
104
105   if(name==NULL) return NULL;
106
107   p=pointer;
108   n_start=name;
109
110   if(p->name != NULL){ /* has *pointer a name ? */
111     n_end=strchr(n_start,'.');     /* search the first dot */
112     if(n_end){
113       memcpy(n,n_start,n_end-n_start);
114       n[n_end-n_start]=0;
115       n_start=n_end;
116       n_start++;
117     }
118     else{
119       _asn1_str_cpy(n,sizeof(n),n_start);
120       n_start=NULL;
121     }
122     
123     while(p){
124       if((p->name) && (!strcmp(p->name,n))) break;
125       else p=p->right;
126     } /* while */
127     
128     if(p==NULL) return NULL;
129   }
130   else{ /* *pointer doesn't have a name */
131     if(n_start[0]==0)
132       return p;
133   }
134
135   while(n_start){   /* Has the end of NAME been reached? */
136     n_end=strchr(n_start,'.');    /* search the next dot */
137     if(n_end){
138       memcpy(n,n_start,n_end-n_start);
139       n[n_end-n_start]=0;
140       n_start=n_end;
141       n_start++;
142     }
143     else{
144       _asn1_str_cpy(n,sizeof(n),n_start);
145       n_start=NULL;
146     }
147
148     if(p->down==NULL) return NULL;
149
150     p=p->down;
151
152     /* The identifier "?LAST" indicates the last element 
153        in the right chain. */
154     if(!strcmp(n,"?LAST")){
155       if(p==NULL) return NULL;
156       while(p->right) p=p->right;
157     }
158     else{   /* no "?LAST" */
159       while(p){
160         if((p->name) && (!strcmp(p->name,n))) break;
161         else p=p->right;
162       }
163       if(p==NULL) return NULL;
164     }
165   } /* while */
166
167   return p;
168 }
169
170
171 /******************************************************************/
172 /* Function : _asn1_set_value                                     */
173 /* Description: sets the field VALUE in a NODE_ASN element. The   */
174 /*              previus value (if exist) will be lost             */
175 /* Parameters:                                                    */
176 /*   node: element pointer.                                       */
177 /*   value: pointer to the value that you want to set.            */
178 /*   len: character number of value.                              */
179 /* Return: pointer to the NODE_ASN element.                       */
180 /******************************************************************/
181 node_asn *
182 _asn1_set_value(node_asn *node,const unsigned char *value,unsigned int len)
183 {
184
185   if(node==NULL) return node;
186   if(node->value){
187     _asn1_free(node->value);
188     node->value=NULL;  
189   }
190   if(!len) return node;
191   node->value=(unsigned char *) _asn1_malloc(len);
192   if (node->value==NULL) return NULL;
193   
194   memcpy(node->value,value,len);
195   return node;
196 }
197
198 /******************************************************************/
199 /* Function : _asn1_set_name                                      */
200 /* Description: sets the field NAME in a NODE_ASN element. The    */
201 /*              previus value (if exist) will be lost             */
202 /* Parameters:                                                    */
203 /*   node: element pointer.                                       */
204 /*   name: a null terminated string with the name that you want   */
205 /*         to set.                                                */
206 /* Return: pointer to the NODE_ASN element.                       */
207 /******************************************************************/
208 node_asn *
209 _asn1_set_name(node_asn *node,const char *name)
210 {
211   if(node==NULL) return node;
212
213   if(node->name){
214     _asn1_free(node->name);
215     node->name=NULL;
216   }
217
218   if(name==NULL) return node;
219
220   if(strlen(name))
221         {
222         node->name=(char *) _asn1_strdup( name);
223         if (node->name==NULL) return NULL;
224       }
225   else node->name=NULL;
226   return node;
227 }
228
229 /******************************************************************/
230 /* Function : _asn1_set_right                                     */
231 /* Description: sets the field RIGHT in a NODE_ASN element.       */
232 /* Parameters:                                                    */
233 /*   node: element pointer.                                       */
234 /*   right: pointer to a NODE_ASN element that you want be pointed*/
235 /*          by NODE.                                              */
236 /* Return: pointer to *NODE.                                      */
237 /******************************************************************/
238 node_asn *
239 _asn1_set_right(node_asn *node,node_asn *right)
240 {
241   if(node==NULL) return node;
242   node->right=right;
243   if(right) right->left=node;
244   return node;
245 }
246
247 /******************************************************************/
248 /* Function : _asn1_get_right                                     */
249 /* Description: returns the element pointed by the RIGHT field of */
250 /*              a NODE_ASN element.                               */
251 /* Parameters:                                                    */
252 /*   node: NODE_ASN element pointer.                              */
253 /* Return: field RIGHT of NODE.                                   */
254 /******************************************************************/
255 node_asn *
256 _asn1_get_right(node_asn *node)
257 {
258   if(node==NULL) return NULL;
259   return node->right;
260 }
261
262 /******************************************************************/
263 /* Function : _asn1_get_last_right                                */
264 /* Description: return the last element along the right chain.    */
265 /* Parameters:                                                    */
266 /*   node: starting element pointer.                              */
267 /* Return: pointer to the last element along the right chain.     */
268 /******************************************************************/
269 node_asn *
270 _asn1_get_last_right(node_asn *node)
271 {
272   node_asn *p;
273
274   if(node==NULL) return NULL;
275   p=node;
276   while(p->right) p=p->right;
277   return p;
278 }
279
280 /******************************************************************/
281 /* Function : _asn1_set_down                                      */
282 /* Description: sets the field DOWN in a NODE_ASN element.        */
283 /* Parameters:                                                    */
284 /*   node: element pointer.                                       */
285 /*   down: pointer to a NODE_ASN element that you want be pointed */
286 /*          by NODE.                                              */
287 /* Return: pointer to *NODE.                                      */
288 /******************************************************************/
289 node_asn *
290 _asn1_set_down(node_asn *node,node_asn *down)
291 {
292   if(node==NULL) return node;
293   node->down=down;
294   if(down) down->left=node;
295   return node;
296 }
297
298 /******************************************************************/
299 /* Function : _asn1_get_down                                      */
300 /* Description: returns the element pointed by the DOWN field of  */
301 /*              a NODE_ASN element.                               */
302 /* Parameters:                                                    */
303 /*   node: NODE_ASN element pointer.                              */
304 /* Return: field DOWN of NODE.                                    */
305 /******************************************************************/
306 node_asn *
307 _asn1_get_down(node_asn *node)
308 {
309   if(node==NULL) return NULL;
310   return node->down;
311 }
312
313 /******************************************************************/
314 /* Function : _asn1_get_name                                      */
315 /* Description: returns the name of a NODE_ASN element.           */
316 /* Parameters:                                                    */
317 /*   node: NODE_ASN element pointer.                              */
318 /* Return: a null terminated string.                              */
319 /******************************************************************/
320 char *
321 _asn1_get_name(node_asn *node)
322 {
323   if(node==NULL) return NULL;
324   return node->name;
325 }
326
327 /******************************************************************/
328 /* Function : _asn1_mod_type                                      */
329 /* Description: change the field TYPE of an NODE_ASN element.     */
330 /*              The new value is the old one | (bitwise or) the   */
331 /*              paramener VALUE.                                  */
332 /* Parameters:                                                    */
333 /*   node: NODE_ASN element pointer.                              */
334 /*   value: the integer value that must be or-ed with the current */
335 /*          value of field TYPE.                                  */
336 /* Return: NODE pointer.                                          */
337 /******************************************************************/
338 node_asn *
339 _asn1_mod_type(node_asn *node,unsigned int value)
340 {
341   if(node==NULL) return node;
342   node->type|=value;
343   return node;
344 }
345
346
347 /******************************************************************/
348 /* Function : _asn1_remove_node                                   */
349 /* Description: gets free the memory allocated for an NODE_ASN    */
350 /*              element (not the elements pointed by it).         */
351 /* Parameters:                                                    */
352 /*   node: NODE_ASN element pointer.                              */
353 /******************************************************************/
354 void
355 _asn1_remove_node(node_asn *node)
356 {
357   if(node==NULL) return;
358
359   if (node->name!=NULL)
360           _asn1_free(node->name);
361   if (node->value!=NULL)
362           _asn1_free(node->value);
363   _asn1_free(node);
364 }
365
366 /******************************************************************/
367 /* Function : _asn1_find_up                                       */
368 /* Description: return the father of the NODE_ASN element.        */
369 /* Parameters:                                                    */
370 /*   node: NODE_ASN element pointer.                              */
371 /* Return: Null if not found.                                     */ 
372 /******************************************************************/
373 node_asn *
374 _asn1_find_up(node_asn *node)
375 {
376   node_asn *p;
377
378   if(node==NULL) return NULL;
379
380   p=node;
381
382   while((p->left!=NULL) && (p->left->right==p)) p=p->left;
383
384   return p->left;
385 }
386
387 /******************************************************************/
388 /* Function : _asn1_delete_list                                   */
389 /* Description: deletes the list elements (not the elements       */
390 /*  pointed by them).                                             */
391 /******************************************************************/
392 void
393 _asn1_delete_list(void)
394 {
395   list_type *listElement;
396
397   while(firstElement){
398     listElement=firstElement;
399     firstElement=firstElement->next;
400     _asn1_free(listElement);
401   }
402 }
403
404 /******************************************************************/
405 /* Function : _asn1_delete_list_and nodes                         */
406 /* Description: deletes the list elements and the elements        */
407 /*  pointed by them.                                              */
408 /******************************************************************/
409 void
410 _asn1_delete_list_and_nodes(void)
411 {
412   list_type *listElement;
413
414   while(firstElement){
415     listElement=firstElement;
416     firstElement=firstElement->next;
417     _asn1_remove_node(listElement->node);
418     _asn1_free(listElement);
419   }
420 }
421
422
423 char *
424 _asn1_ltostr(long v,char *str)
425 {
426   long d,r;
427   char temp[20];
428   int count,k,start;
429
430   if(v<0){
431     str[0]='-';
432     start=1;
433     v=-v;
434   }
435   else start=0;
436
437   count=0;
438   do{
439     d=v/10;
440     r=v-d*10;
441     temp[start+count]='0'+(char)r;
442     count++;
443     v=d;
444   }while(v);
445
446   for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
447   str[count+start]=0;
448   return str;
449 }
450
451
452 /******************************************************************/
453 /* Function : _asn1_change_integer_value                          */
454 /* Description: converts into DER coding the value assign to an   */
455 /*   INTEGER constant.                                            */
456 /* Parameters:                                                    */
457 /*   node: root of an ASN1element.                                */
458 /* Return:                                                        */
459 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
460 /*   otherwise ASN1_SUCCESS                                             */
461 /******************************************************************/
462 asn1_retCode 
463 _asn1_change_integer_value(ASN1_TYPE node)
464 {
465   node_asn *p;
466   unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
467   unsigned char val2[SIZEOF_UNSIGNED_LONG_INT+1];
468   int len;
469
470   if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
471
472   p=node;
473   while(p){
474     if((type_field(p->type)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){
475       if(p->value){
476         _asn1_convert_integer(p->value,val,sizeof(val), &len);  
477         _asn1_octet_der(val,len,val2,&len);
478         _asn1_set_value(p,val2,len);
479       }
480     }
481
482     if(p->down){
483       p=p->down;
484     }
485     else{
486       if(p==node) p=NULL;
487       else if(p->right) p=p->right;
488       else{
489         while(1){
490           p=_asn1_find_up(p);
491           if(p==node){
492             p=NULL;
493             break;
494           }
495           if(p->right){
496             p=p->right;
497             break;
498           }
499         }
500       }
501     }
502   }
503
504   return ASN1_SUCCESS;
505 }
506
507
508 /******************************************************************/
509 /* Function : _asn1_expand_object_id                              */
510 /* Description: expand the IDs of an OBJECT IDENTIFIER constant.  */
511 /* Parameters:                                                    */
512 /*   node: root of an ASN1 element.                               */
513 /* Return:                                                        */
514 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
515 /*   otherwise ASN1_SUCCESS                                             */
516 /******************************************************************/
517 asn1_retCode
518 _asn1_expand_object_id(ASN1_TYPE node)
519 {
520   node_asn *p,*p2,*p3,*p4,*p5;
521   char name_root[129],name2[129];
522   int move;
523  
524   if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
525
526   _asn1_str_cpy(name_root, sizeof(name_root), node->name);
527
528   p=node;
529   move=DOWN;
530
531   while(!((p==node) && (move==UP))){
532     if(move!=UP){
533       if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){
534         p2=p->down;
535         if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
536           if(p2->value && !isdigit(p2->value[0])){
537             _asn1_str_cpy(name2, sizeof(name2), name_root);
538             _asn1_str_cat(name2, sizeof(name2), ".");
539             _asn1_str_cat(name2, sizeof(name2), p2->value);
540             p3=_asn1_find_node(node,name2);
541             if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) ||
542                !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND;
543             _asn1_set_down(p,p2->right);
544             _asn1_remove_node(p2);
545             p2=p;
546             p4=p3->down;
547             while(p4){
548               if(type_field(p4->type)==TYPE_CONSTANT){
549                 p5=_asn1_add_node_only(TYPE_CONSTANT);
550                 _asn1_set_name(p5,p4->name);
551                 _asn1_set_value(p5,p4->value,strlen(p4->value)+1);
552                 if(p2==p){
553                   _asn1_set_right(p5,p->down);
554                   _asn1_set_down(p,p5);
555                 }
556                 else{
557                   _asn1_set_right(p5,p2->right);
558                   _asn1_set_right(p2,p5);
559                 }
560                 p2=p5;
561               }
562               p4=p4->right;
563             }
564             move=DOWN;
565             continue;
566           }
567         }
568       }
569       move=DOWN;
570     }
571     else move=RIGHT;
572
573     if(move==DOWN){
574       if(p->down) p=p->down;
575       else move=RIGHT;
576     }
577     
578     if(p==node) {move=UP; continue;}
579
580     if(move==RIGHT){
581       if(p->right) p=p->right;
582       else move=UP;
583     }
584     if(move==UP) p=_asn1_find_up(p);
585   }
586
587   return ASN1_SUCCESS;
588 }
589
590
591 /******************************************************************/
592 /* Function : _asn1_type_set_config                               */
593 /* Description: sets the CONST_SET and CONST_NOT_USED properties  */
594 /*   in the fields of the SET elements.                           */
595 /* Parameters:                                                    */
596 /*   node: root of an ASN1 element.                               */
597 /* Return:                                                        */
598 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
599 /*   otherwise ASN1_SUCCESS                                             */
600 /******************************************************************/
601 asn1_retCode 
602 _asn1_type_set_config(ASN1_TYPE node)
603 {
604   node_asn *p,*p2;
605   int move;
606  
607   if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
608
609   p=node;
610   move=DOWN;
611
612   while(!((p==node) && (move==UP))){
613     if(move!=UP){
614       if(type_field(p->type)==TYPE_SET){
615         p2=p->down;
616         while(p2){
617           if(type_field(p2->type)!=TYPE_TAG) 
618             p2->type|=CONST_SET|CONST_NOT_USED;
619           p2=p2->right;
620         }
621       }
622       move=DOWN;
623     }
624     else move=RIGHT;
625
626     if(move==DOWN){
627       if(p->down) p=p->down;
628       else move=RIGHT;
629     }
630
631     if(p==node) {move=UP; continue;}
632
633     if(move==RIGHT){
634       if(p->right) p=p->right;
635       else move=UP;
636     }
637     if(move==UP) p=_asn1_find_up(p);
638   }
639
640   return ASN1_SUCCESS;
641 }
642
643
644 /******************************************************************/
645 /* Function : _asn1_check_identifier                              */
646 /* Description: checks the definitions of all the identifiers     */
647 /*   and the first element of an OBJECT_ID (e.g. {pkix 0 4}).     */
648 /*   The _asn1_identifierMissing global variable is filled if     */
649 /*   necessary.                                                   */
650 /* Parameters:                                                    */
651 /*   node: root of an ASN1 element.                               */
652 /* Return:                                                        */
653 /*   ASN1_ELEMENT_NOT_FOUND      if NODE is NULL,                 */
654 /*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
655 /*   otherwise ASN1_SUCCESS                                       */
656 /******************************************************************/
657 asn1_retCode 
658 _asn1_check_identifier(ASN1_TYPE node)
659 {
660   node_asn *p,*p2;
661   char name2[MAX_NAME_SIZE*2+2];
662
663   if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
664
665   p=node;
666   while(p){
667     if(type_field(p->type)==TYPE_IDENTIFIER){
668       _asn1_str_cpy(name2, sizeof(name2), node->name);
669       _asn1_str_cat(name2, sizeof(name2), ".");
670       _asn1_str_cat(name2, sizeof(name2), p->value);
671       p2=_asn1_find_node(node,name2);
672       if(p2==NULL){
673         strcpy(_asn1_identifierMissing,p->value);
674         return ASN1_IDENTIFIER_NOT_FOUND;
675       } 
676     }
677     else if((type_field(p->type)==TYPE_OBJECT_ID) && 
678             (p->type&CONST_ASSIGN)){
679       p2=p->down;
680       if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
681         if(p2->value && !isdigit(p2->value[0])){
682           _asn1_str_cpy(name2, sizeof(name2), node->name);
683           _asn1_str_cat(name2, sizeof(name2), ".");
684           _asn1_str_cat(name2, sizeof(name2), p2->value);
685           strcpy(_asn1_identifierMissing,p2->value);
686           p2=_asn1_find_node(node,name2);
687           if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
688              !(p2->type&CONST_ASSIGN))
689             return ASN1_IDENTIFIER_NOT_FOUND;
690           else
691             _asn1_identifierMissing[0]=0;
692         }
693       }
694     }
695     
696     if(p->down){
697       p=p->down;
698     }
699     else if(p->right) p=p->right;
700     else{
701       while(1){
702         p=_asn1_find_up(p);
703         if(p==node){
704           p=NULL;
705           break;
706         }
707         if(p->right){
708           p=p->right;
709           break;
710         }
711       }
712     }
713   }
714
715   return ASN1_SUCCESS;
716 }
717
718
719 /******************************************************************/
720 /* Function : _asn1_set_default_tag                               */
721 /* Description: sets the default IMPLICIT or EXPLICIT property in */
722 /*   the tagged elements that don't have this declaration.        */
723 /* Parameters:                                                    */
724 /*   node: pointer to a DEFINITIONS element.                      */
725 /* Return:                                                        */
726 /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to    */
727 /*     a DEFINITIONS element,                                     */
728 /*   otherwise ASN1_SUCCESS                                             */
729 /******************************************************************/
730 asn1_retCode 
731 _asn1_set_default_tag(ASN1_TYPE node)
732 {
733   node_asn *p;
734
735   if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS))
736     return ASN1_ELEMENT_NOT_FOUND; 
737
738   p=node;
739   while(p){
740     if((type_field(p->type)==TYPE_TAG) &&
741             !(p->type&CONST_EXPLICIT) &&
742             !(p->type&CONST_IMPLICIT)){
743       if(node->type&CONST_EXPLICIT) p->type|=CONST_EXPLICIT;
744       else p->type|=CONST_IMPLICIT;
745     }
746
747     if(p->down){
748       p=p->down;
749     }
750     else if(p->right) p=p->right;
751     else{
752       while(1){
753           p=_asn1_find_up(p);
754           if(p==node){
755             p=NULL;
756             break;
757           }
758           if(p->right){
759             p=p->right;
760             break;
761           }
762       }
763     }
764   }
765
766   return ASN1_SUCCESS;
767 }
768
769
770
771