*** empty log message ***
[gnutls.git] / lib / x509_asn1.c
blob81a441ba99937b4ebc42eae3755a4c9a2e46513c
1 /*
2 * Copyright (C) 2000,2001 Fabio Fiorina
4 * This file is part of GNUTLS.
6 * The GNUTLS 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.
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.
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
23 /*****************************************************/
24 /* File: x509_asn1.c */
25 /* Description: Functions to manage ASN.1 DEFINITIONS*/
26 /*****************************************************/
29 #include <gnutls_int.h>
30 #include <gnutls_errors.h>
31 #include "x509_asn1.h"
32 #include "x509_der.h"
33 #include <gnutls_str.h>
35 /* define used for visiting trees */
36 #define UP 1
37 #define RIGHT 2
38 #define DOWN 3
41 int parse_mode; /* PARSE_MODE_CHECK = only syntax check
42 PARSE_MODE_CREATE = structure creation */
45 /******************************************************/
46 /* Function : _asn1_add_node */
47 /* Description: creates a new NODE_ASN element. */
48 /* Parameters: */
49 /* type: type of the new element (see TYPE_ */
50 /* and CONST_ constants). */
51 /* Return: pointer to the new element. */
52 /******************************************************/
53 node_asn *
54 _asn1_add_node(unsigned int type)
56 node_asn *punt;
58 if(parse_mode==PARSE_MODE_CHECK) return NULL;
60 punt=(node_asn *) gnutls_malloc(sizeof(node_asn));
61 if (punt==NULL) return NULL;
63 punt->left=NULL;
64 punt->name=NULL;
65 punt->type=type;
66 punt->value=NULL;
67 punt->down=NULL;
68 punt->right=NULL;
70 return punt;
73 /******************************************************************/
74 /* Function : _asn1_set_value */
75 /* Description: sets the field VALUE in a NODE_ASN element. The */
76 /* previus value (if exist) will be lost */
77 /* Parameters: */
78 /* node: element pointer. */
79 /* value: pointer to the value that you want to set. */
80 /* len: character number of value. */
81 /* Return: pointer to the NODE_ASN element. */
82 /******************************************************************/
83 node_asn *
84 _asn1_set_value(node_asn *node,unsigned char *value,unsigned int len)
86 if(parse_mode==PARSE_MODE_CHECK) return NULL;
88 if(node==NULL) return node;
89 if(node->value){
90 gnutls_free(node->value);
91 node->value=NULL;
93 if(!len) return node;
94 node->value=(unsigned char *) gnutls_malloc(len);
95 if (node->value==NULL) return NULL;
97 memcpy(node->value,value,len);
98 return node;
101 /******************************************************************/
102 /* Function : _asn1_set_name */
103 /* Description: sets the field NAME in a NODE_ASN element. The */
104 /* previus value (if exist) will be lost */
105 /* Parameters: */
106 /* node: element pointer. */
107 /* name: a null terminated string with the name that you want */
108 /* to set. */
109 /* Return: pointer to the NODE_ASN element. */
110 /******************************************************************/
111 node_asn *
112 _asn1_set_name(node_asn *node,char *name)
114 if(parse_mode==PARSE_MODE_CHECK) return NULL;
116 if(node==NULL) return node;
118 if(node->name){
119 gnutls_free(node->name);
120 node->name=NULL;
123 if(name==NULL) return node;
125 if(strlen(name))
127 node->name=(char *) gnutls_strdup( name);
128 if (node->name==NULL) return NULL;
130 else node->name=NULL;
131 return node;
134 /******************************************************************/
135 /* Function : _asn1_set_right */
136 /* Description: sets the field RIGHT in a NODE_ASN element. */
137 /* Parameters: */
138 /* node: element pointer. */
139 /* right: pointer to a NODE_ASN element that you want be pointed*/
140 /* by NODE. */
141 /* Return: pointer to *NODE. */
142 /******************************************************************/
143 node_asn *
144 _asn1_set_right(node_asn *node,node_asn *right)
146 if(parse_mode==PARSE_MODE_CHECK) return NULL;
148 if(node==NULL) return node;
149 node->right=right;
150 if(right) right->left=node;
151 return node;
154 /******************************************************************/
155 /* Function : _asn1_get_right */
156 /* Description: returns the element pointed by the RIGHT field of */
157 /* a NODE_ASN element. */
158 /* Parameters: */
159 /* node: NODE_ASN element pointer. */
160 /* Return: field RIGHT of NODE. */
161 /******************************************************************/
162 node_asn *
163 _asn1_get_right(node_asn *node)
165 if(parse_mode==PARSE_MODE_CHECK) return NULL;
167 if(node==NULL) return NULL;
168 return node->right;
171 /******************************************************************/
172 /* Function : _asn1_get_last_right */
173 /* Description: return the last element along the right chain. */
174 /* Parameters: */
175 /* node: starting element pointer. */
176 /* Return: pointer to the last element along the right chain. */
177 /******************************************************************/
178 node_asn *
179 _asn1_get_last_right(node_asn *node)
181 node_asn *p;
183 if(parse_mode==PARSE_MODE_CHECK) return NULL;
184 if(node==NULL) return NULL;
185 p=node;
186 while(p->right) p=p->right;
187 return p;
190 /******************************************************************/
191 /* Function : _asn1_set_down */
192 /* Description: sets the field DOWN in a NODE_ASN element. */
193 /* Parameters: */
194 /* node: element pointer. */
195 /* down: pointer to a NODE_ASN element that you want be pointed */
196 /* by NODE. */
197 /* Return: pointer to *NODE. */
198 /******************************************************************/
199 node_asn *
200 _asn1_set_down(node_asn *node,node_asn *down)
202 if(parse_mode==PARSE_MODE_CHECK) return NULL;
204 if(node==NULL) return node;
205 node->down=down;
206 if(down) down->left=node;
207 return node;
210 /******************************************************************/
211 /* Function : _asn1_get_down */
212 /* Description: returns the element pointed by the DOWN field of */
213 /* a NODE_ASN element. */
214 /* Parameters: */
215 /* node: NODE_ASN element pointer. */
216 /* Return: field DOWN of NODE. */
217 /******************************************************************/
218 node_asn *
219 _asn1_get_down(node_asn *node)
221 if(parse_mode==PARSE_MODE_CHECK) return NULL;
223 if(node==NULL) return NULL;
224 return node->down;
227 /******************************************************************/
228 /* Function : _asn1_get_name */
229 /* Description: returns the name of a NODE_ASN element. */
230 /* Parameters: */
231 /* node: NODE_ASN element pointer. */
232 /* Return: a null terminated string. */
233 /******************************************************************/
234 char *
235 _asn1_get_name(node_asn *node)
237 if(parse_mode==PARSE_MODE_CHECK) return NULL;
239 if(node==NULL) return NULL;
240 return node->name;
243 /******************************************************************/
244 /* Function : _asn1_mod_type */
245 /* Description: change the field TYPE of an NODE_ASN element. */
246 /* The new value is the old one | (bitwise or) the */
247 /* paramener VALUE. */
248 /* Parameters: */
249 /* node: NODE_ASN element pointer. */
250 /* value: the integer value that must be or-ed with the current */
251 /* value of field TYPE. */
252 /* Return: NODE pointer. */
253 /******************************************************************/
254 node_asn *
255 _asn1_mod_type(node_asn *node,unsigned int value)
257 if(parse_mode==PARSE_MODE_CHECK) return NULL;
259 if(node==NULL) return node;
260 node->type|=value;
261 return node;
264 /******************************************************************/
265 /* Function : _asn1_remove_node */
266 /* Description: gets free the memory allocated for an NODE_ASN */
267 /* element (not the elements pointed by it). */
268 /* Parameters: */
269 /* node: NODE_ASN element pointer. */
270 /******************************************************************/
271 void
272 _asn1_remove_node(node_asn *node)
274 if(node==NULL) return;
276 if (node->name!=NULL)
277 gnutls_free(node->name);
278 if (node->value!=NULL)
279 gnutls_free(node->value);
280 gnutls_free(node);
284 /******************************************************************/
285 /* Function : _asn1_find_mode */
286 /* Description: searches an element called NAME starting from */
287 /* POINTER. The name is composed by differents */
288 /* identifiers separated by dot.The first identifier */
289 /* must be the name of *POINTER. */
290 /* Parameters: */
291 /* pointer: NODE_ASN element pointer. */
292 /* name: null terminated string with the element's name to find.*/
293 /* Return: the searching result. NULL if not find. */
294 /******************************************************************/
295 node_asn *
296 _asn1_find_node(node_asn *pointer,char *name)
298 node_asn *p;
299 char *n_start,*n_end,n[128];
301 if((name==NULL) || (name[0]==0)) return NULL;
303 n_start=name;
304 n_end=strchr(n_start,'.'); /* search the first dot */
305 if(n_end){
306 memcpy(n,n_start,n_end-n_start);
307 n[n_end-n_start]=0;
308 n_start=n_end;
309 n_start++;
311 else{
312 _gnutls_str_cpy(n,sizeof(n),n_start);
313 n_start=NULL;
316 p=pointer;
317 while(p){
318 if((p->name) && (!strcmp(p->name,n))) break;
319 else p=p->right;
320 } /* while */
322 if(p==NULL) return NULL;
324 while(n_start){ /* Has the end of NAME been reached? */
325 n_end=strchr(n_start,'.'); /* search the next dot */
326 if(n_end){
327 memcpy(n,n_start,n_end-n_start);
328 n[n_end-n_start]=0;
329 n_start=n_end;
330 n_start++;
332 else{
333 _gnutls_str_cpy(n,sizeof(n),n_start);
334 n_start=NULL;
337 if(p->down==NULL) return NULL;
339 p=p->down;
341 /* The identifier "?LAST" indicates the last element
342 in the right chain. */
343 if(!strcmp(n,"?LAST")){
344 if(p==NULL) return NULL;
345 while(p->right) p=p->right;
347 else{ /* no "?LAST" */
348 while(p){
349 if((p->name) && (!strcmp(p->name,n))) break;
350 else p=p->right;
352 if(p==NULL) return NULL;
354 } /* while */
356 return p;
359 /******************************************************************/
360 /* Function : _asn1_find_left */
361 /* Description: returns the NODE_ASN element with RIGHT field that*/
362 /* points the element NODE. */
363 /* Parameters: */
364 /* node: NODE_ASN element pointer. */
365 /* Return: NULL if not found. */
366 /******************************************************************/
367 node_asn *
368 _asn1_find_left(node_asn *node)
370 if((node==NULL) || (node->left==NULL) ||
371 (node->left->down==node)) return NULL;
373 return node->left;
376 /******************************************************************/
377 /* Function : _asn1_find_up */
378 /* Description: return the father of the NODE_ASN element. */
379 /* Parameters: */
380 /* node: NODE_ASN element pointer. */
381 /* Return: Null if not found. */
382 /******************************************************************/
383 node_asn *
384 _asn1_find_up(node_asn *node)
386 node_asn *p;
388 if(node==NULL) return NULL;
390 p=node;
392 while((p->left!=NULL) && (p->left->right==p)) p=p->left;
394 return p->left;
397 /******************************************************************/
398 /* Function : _asn1_convert_integer */
399 /* Description: converts an integer from a null terminated string */
400 /* to der decoding. The convertion from a null */
401 /* terminated string to an integer is made with */
402 /* the 'strtol' function. */
403 /* Parameters: */
404 /* value: null terminated string to convert. */
405 /* value_out: convertion result (memory must be already */
406 /* allocated). */
407 /* value_out_size: number of bytes of value_out. */
408 /* len: number of significant byte of value_out. */
409 /* Return: ASN_MEM_ERROR or ASN_OK */
410 /******************************************************************/
412 _asn1_convert_integer(char *value,unsigned char *value_out,int value_out_size, int *len)
414 char negative;
415 unsigned char val[4],temp;
416 int k,k2;
418 *((long*)val)=strtol(value,NULL,10);
419 for(k=0;k<2;k++){
420 temp=val[k];
421 val[k]=val[3-k];
422 val[3-k]=temp;
425 if(val[0]&0x80) negative=1;
426 else negative=0;
428 for(k=0;k<3;k++){
429 if(negative && (val[k]!=0xFF)) break;
430 else if(!negative && val[k]) break;
433 if((negative && !(val[k]&0x80)) ||
434 (!negative && (val[k]&0x80))) k--;
436 for(k2=k;k2<4;k2++) {
437 if (k2-k > value_out_size-1) {
438 gnutls_assert();
439 return ASN_MEM_ERROR;
441 /* VALUE_OUT is too short to contain the value convertion */
442 value_out[k2-k]=val[k2];
444 *len=4-k;
446 return ASN_OK;
450 * asn1_create_tree - Creates the structures needed to manage the ASN1 definitions.
451 * @root: specify vector that contains ASN.1 declarations
452 * @pointer: return the pointer to the structure created by *ROOT ASN.1 declarations
453 * Description:
455 * Creates the structures needed to manage the ASN1 definitions. ROOT is a vector created by
456 * 'asn1_parser_asn1_file_c' function.
458 * Returns:
460 * ASN_OK\: structure created correctly.
462 * ASN_GENERIC_ERROR\: an error occured while structure creation
465 asn1_create_tree(const static_asn *root,node_asn **pointer)
467 node_asn *p,*p_last;
468 unsigned long k;
469 int move;
471 *pointer=NULL;
472 move=UP;
474 k=0;
475 while(root[k].value || root[k].type || root[k].name){
476 p=_asn1_add_node(root[k].type&(~CONST_DOWN));
477 if(root[k].name) _asn1_set_name(p,root[k].name);
478 if(root[k].value) _asn1_set_value(p,root[k].value,strlen(root[k].value)+1);
480 if(*pointer==NULL) *pointer=p;
482 if(move==DOWN) _asn1_set_down(p_last,p);
483 else if(move==RIGHT) _asn1_set_right(p_last,p);
485 p_last=p;
487 if(root[k].type&CONST_DOWN) move=DOWN;
488 else if(root[k].type&CONST_RIGHT) move=RIGHT;
489 else{
490 while(1){
491 if(p_last==*pointer) break;
493 p_last= _asn1_find_up(p_last);
495 if(p_last==NULL) break;
497 if(p_last->type&CONST_RIGHT){
498 p_last->type&=~CONST_RIGHT;
499 move=RIGHT;
500 break;
502 } /* while */
504 k++;
505 } /* while */
507 if(p_last==*pointer){
508 _asn1_change_integer_value(*pointer);
509 _asn1_expand_object_id(*pointer);
511 else asn1_delete_structure(*pointer);
513 return (p_last==*pointer)?ASN_OK:ASN_GENERIC_ERROR;
518 _asn1_create_static_structure(node_asn *pointer,char *file_name, char* out_name)
520 FILE *file;
521 node_asn *p;
522 unsigned long t;
523 char structure_name[128],file_out_name[128],*char_p,*slash_p,*dot_p;
525 char_p=file_name;
526 slash_p=file_name;
527 while((char_p=strchr(char_p,'/'))){
528 char_p++;
529 slash_p=char_p;
532 char_p=slash_p;
533 dot_p=file_name+strlen(file_name);
535 while((char_p=strchr(char_p,'.'))){
536 dot_p=char_p;
537 char_p++;
540 memcpy(structure_name,slash_p,dot_p-slash_p);
541 structure_name[dot_p-slash_p]=0;
542 _gnutls_str_cat(structure_name, sizeof(structure_name),"_asn1_tab");
544 if (out_name==NULL) {
545 memcpy(file_out_name,file_name,dot_p-file_name);
546 file_out_name[dot_p-file_name]=0;
547 _gnutls_str_cat(file_out_name, sizeof(file_out_name), "_asn1_tab.c");
548 } else {
549 _gnutls_str_cpy( file_out_name, sizeof(file_out_name), out_name);
551 file=fopen( file_out_name,"w");
553 if(file==NULL) return ASN_FILE_NOT_FOUND;
555 fprintf(file,"\n#include \"x509_asn1.h\"\n\n");
556 fprintf(file,"const static_asn %s[]={\n",structure_name);
558 p=pointer;
560 while(p){
561 fprintf(file," {");
563 if(p->name) fprintf(file,"\"%s\",",p->name);
564 else fprintf(file,"0,");
566 t=p->type;
567 if(p->down) t|=CONST_DOWN;
568 if(p->right) t|=CONST_RIGHT;
570 fprintf(file,"%lu,",t);
572 if(p->value) fprintf(file,"\"%s\"},\n",p->value);
573 else fprintf(file,"0},\n");
575 if(p->down){
576 p=p->down;
578 else if(p->right){
579 p=p->right;
581 else{
582 while(1){
583 p=_asn1_find_up(p);
584 if(p==pointer){
585 p=NULL;
586 break;
588 if(p->right){
589 p=p->right;
590 break;
596 fprintf(file," {0,0,0}\n};\n");
598 fclose(file);
600 return ASN_OK;
605 * asn1_visit_tree - Prints on the standard output the structure's tree
606 * @pointer: pointer to the structure that you want to delete.
607 * @name: an element of the structure
609 * Prints on the standard output the structure's tree starting from the NAME element inside
610 * the structure *POINTER.
612 void
613 asn1_visit_tree(node_asn *pointer,char *name)
615 node_asn *p,*root;
616 int k,indent=0,len,len2,len3;
618 root=_asn1_find_node(pointer,name);
620 if(root==NULL) return;
622 p=root;
623 while(p){
624 for(k=0;k<indent;k++)printf(" ");
626 printf("name:");
627 if(p->name) printf("%s ",p->name);
628 else printf("NULL ");
630 printf("type:");
631 switch(type_field(p->type)){
632 case TYPE_NULL:
633 printf("NULL");
634 break;
635 case TYPE_CONSTANT:
636 printf("CONST");
637 if(p->value) printf(" value:%s",p->value);
638 break;
639 case TYPE_IDENTIFIER:
640 printf("IDENTIFIER");
641 if(p->value) printf(" value:%s",p->value);
642 break;
643 case TYPE_INTEGER:
644 printf("INTEGER");
645 if(p->value){
646 len2=-1;
647 len=_asn1_get_length_der(p->value,&len2);
648 printf(" value:0x");
649 for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
651 break;
652 case TYPE_ENUMERATED:
653 printf("ENUMERATED");
654 if(p->value){
655 len2=-1;
656 len=_asn1_get_length_der(p->value,&len2);
657 printf(" value:0x");
658 for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
660 break;
661 case TYPE_TIME:
662 printf("TIME");
663 if(p->value) printf(" value:%s",p->value);
664 break;
665 case TYPE_BOOLEAN:
666 printf("BOOLEAN");
667 if(p->value){
668 if(p->value[0]=='T') printf(" value:TRUE");
669 else if(p->value[0]=='F') printf(" value:FALSE");
671 break;
672 case TYPE_SEQUENCE:
673 printf("SEQUENCE");
674 break;
675 case TYPE_BIT_STRING:
676 printf("BIT_STR");
677 if(p->value){
678 len2=-1;
679 len=_asn1_get_length_der(p->value,&len2);
680 printf(" value(%i):",(len-1)*8-(p->value[len2]));
681 for(k=1;k<len;k++) printf("%02x",(p->value)[k+len2]);
683 break;
684 case TYPE_OCTET_STRING:
685 printf("OCT_STR");
686 if(p->value){
687 len2=-1;
688 len=_asn1_get_length_der(p->value,&len2);
689 printf(" value:");
690 for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]);
692 break;
693 case TYPE_TAG:
694 printf("TAG");
695 printf(" value:%s",p->value);
696 break;
697 case TYPE_DEFAULT:
698 printf("DEFAULT");
699 if(p->value) printf(" value:%s",p->value);
700 break;
701 case TYPE_SIZE:
702 printf("SIZE");
703 if(p->value) printf(" value:%s",p->value);
704 break;
705 case TYPE_SEQUENCE_OF:
706 printf("SEQ_OF");
707 break;
708 case TYPE_OBJECT_ID:
709 printf("OBJ_ID");
710 if(p->value) printf(" value:%s",p->value);
711 break;
712 case TYPE_ANY:
713 printf("ANY");
714 if(p->value){
715 len3=-1;
716 len2=_asn1_get_length_der(p->value,&len3);
717 printf(" value:");
718 for(k=0;k<len2;k++) printf("%02x",(p->value)[k+len3]);
721 break;
722 case TYPE_SET:
723 printf("SET");
724 break;
725 case TYPE_SET_OF:
726 printf("SET_OF");
727 break;
728 case TYPE_CHOICE:
729 printf("CHOICE");
730 break;
731 case TYPE_DEFINITIONS:
732 printf("DEFINITIONS");
733 break;
734 default:
735 printf("ERROR\n");
736 break;
739 if(p->type&0xFFFFFF00){
740 printf(" attr:");
741 if(p->type & CONST_UNIVERSAL) printf("UNIVERSAL,");
742 if(p->type & CONST_PRIVATE) printf("PRIVATE,");
743 if(p->type & CONST_APPLICATION) printf("APPLICATION,");
744 if(p->type & CONST_EXPLICIT) printf("EXPLICIT,");
745 if(p->type & CONST_IMPLICIT) printf("IMPLICIT,");
746 if(p->type & CONST_TAG) printf("TAG,");
747 if(p->type & CONST_DEFAULT) printf("DEFAULT,");
748 if(p->type & CONST_TRUE) printf("TRUE,");
749 if(p->type & CONST_FALSE) printf("FALSE,");
750 if(p->type & CONST_LIST) printf("LIST,");
751 if(p->type & CONST_MIN_MAX) printf("MIN_MAX,");
752 if(p->type & CONST_OPTION) printf("OPTION,");
753 if(p->type & CONST_1_PARAM) printf("1_PARAM,");
754 if(p->type & CONST_SIZE) printf("SIZE,");
755 if(p->type & CONST_DEFINED_BY) printf("DEF_BY,");
756 if(p->type & CONST_GENERALIZED) printf("GENERALIZED,");
757 if(p->type & CONST_UTC) printf("UTC,");
758 if(p->type & CONST_IMPORTS) printf("IMPORTS,");
759 if(p->type & CONST_SET) printf("SET,");
760 if(p->type & CONST_NOT_USED) printf("NOT_USED,");
761 if(p->type & CONST_ASSIGN) printf("ASSIGNEMENT,");
764 printf("\n");
766 if(p->down){
767 p=p->down;
768 indent+=2;
770 else if(p==root){
771 p=NULL;
772 break;
774 else if(p->right) p=p->right;
775 else{
776 while(1){
777 p=_asn1_find_up(p);
778 if(p==root){
779 p=NULL;
780 break;
782 indent-=2;
783 if(p->right){
784 p=p->right;
785 break;
794 * asn1_delete_structure - Deletes the structure *POINTER.
795 * @root: pointer to the structure that you want to delete.
796 * Description:
798 * Deletes the structure *POINTER.
800 * Returns:
802 * ASN_OK\: everything OK
804 * ASN_ELEMENT_NOT_FOUND\: pointer==NULL.
808 asn1_delete_structure(node_asn *root)
810 node_asn *p,*p2,*p3;
812 if(root==NULL) return ASN_ELEMENT_NOT_FOUND;
814 p=root;
815 while(p){
816 if(p->down){
817 p=p->down;
819 else{ /* no down */
820 p2=p->right;
821 if(p!=root){
822 p3=_asn1_find_up(p);
823 _asn1_set_down(p3,p2);
824 _asn1_remove_node(p);
825 p=p3;
827 else{ /* p==root */
828 p3=_asn1_find_left(p);
829 if(!p3){
830 p3=_asn1_find_up(p);
831 if(p3) _asn1_set_down(p3,p2);
832 else{
833 if(p->right) p->right->left=NULL;
836 else _asn1_set_right(p3,p2);
837 _asn1_remove_node(p);
838 p=NULL;
842 return ASN_OK;
846 node_asn *
847 _asn1_copy_structure3(node_asn *source_node)
849 node_asn *dest_node,*p_s,*p_d,*p_d_prev;
850 int len,len2,move;
852 if(source_node==NULL) return NULL;
854 dest_node=_asn1_add_node(source_node->type);
856 p_s=source_node;
857 p_d=dest_node;
859 move=DOWN;
862 if(move!=UP){
863 if(p_s->name) _asn1_set_name(p_d,p_s->name);
864 if(p_s->value){
865 switch(type_field(p_s->type)){
866 case TYPE_OCTET_STRING: case TYPE_BIT_STRING:
867 case TYPE_INTEGER: // case TYPE_DEFAULT:
868 len2=-1;
869 len=_asn1_get_length_der(p_s->value,&len2);
870 _asn1_set_value(p_d,p_s->value,len+len2);
871 break;
872 default:
873 _asn1_set_value(p_d,p_s->value,strlen(p_s->value)+1);
876 move=DOWN;
878 else move=RIGHT;
880 if(move==DOWN){
881 if(p_s->down){
882 p_s=p_s->down;
883 p_d_prev=p_d;
884 p_d=_asn1_add_node(p_s->type);
885 _asn1_set_down(p_d_prev,p_d);
887 else move=RIGHT;
890 if(p_s==source_node) break;
892 if(move==RIGHT){
893 if(p_s->right){
894 p_s=p_s->right;
895 p_d_prev=p_d;
896 p_d=_asn1_add_node(p_s->type);
897 _asn1_set_right(p_d_prev,p_d);
899 else move=UP;
901 if(move==UP){
902 p_s=_asn1_find_up(p_s);
903 p_d=_asn1_find_up(p_d);
905 }while(p_s!=source_node);
907 return dest_node;
911 node_asn *
912 _asn1_copy_structure2(node_asn *root,char *source_name)
914 node_asn *source_node;
916 source_node=_asn1_find_node(root,source_name);
918 return _asn1_copy_structure3(source_node);
924 * asn1_create_structure - Creates a structure called DEST_NAME of type SOURCE_NAME.
925 * @root: pointer to the structure returned by "parser_asn1" function
926 * @source_name: the name of the type of the new structure (must be inside p_structure).
927 * @pointer: pointer to the structure created.
928 * @dest_name: the name of the new structure.
929 * Description:
931 * Creates a structure called DEST_NAME of type SOURCE_NAME.
933 * Returns:
935 * ASN_OK\: creation OK
937 * ASN_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known
939 * Example: using "pkix.asn"
940 * result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert,"certificate1");
943 asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer,char *dest_name)
945 node_asn *dest_node;
946 int res;
947 char *end,n[129];
949 *pointer=NULL;
951 dest_node=_asn1_copy_structure2(root,source_name);
953 if(dest_node==NULL) return ASN_ELEMENT_NOT_FOUND;
955 _asn1_set_name(dest_node,dest_name);
957 end=strchr(source_name,'.');
958 if(end){
959 memcpy(n,source_name,end-source_name);
960 n[end-source_name]=0;
962 else{
963 _gnutls_str_cpy(n,sizeof(n),source_name);
966 res=_asn1_expand_identifier(&dest_node,root);
967 _asn1_type_choice_config(dest_node);
969 *pointer=dest_node;
971 return res;
975 int
976 _asn1_append_sequence_set(node_asn *node)
978 node_asn *p,*p2;
979 char temp[10];
980 long n;
982 if(!node || !(node->down)) return ASN_GENERIC_ERROR;
984 p=node->down;
985 while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right;
986 p2=_asn1_copy_structure3(p);
987 while(p->right) p=p->right;
988 _asn1_set_right(p,p2);
990 if(p->name==NULL) _gnutls_str_cpy(temp,sizeof(temp),"?1");
991 else{
992 n=strtol(p->name+1,NULL,0);
993 n++;
994 temp[0]='?';
995 _asn1_ltostr(n,temp+1);
997 _asn1_set_name(p2,temp);
999 return ASN_OK;
1004 * asn1_write_value - Set the value of one element inside a structure.
1005 * @node_root: pointer to a structure
1006 * @name: the name of the element inside the structure that you want to set.
1007 * @value: vector used to specify the value to set. If len is >0,
1008 * VALUE must be a two's complement form integer.
1009 * if len=0 *VALUE must be a null terminated string with an integer value.
1010 * @len: number of bytes of *value to use to set the value: value[0]..value[len-1]
1011 * or 0 if value is a null terminated string
1012 * Description:
1014 * Set the value of one element inside a structure.
1016 * Returns:
1018 * ASN_OK\: set value OK
1020 * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
1022 * ASN_VALUE_NOT_VALID\: VALUE has a wrong format.
1024 * Examples:
1025 * description for each type
1026 * INTEGER: VALUE must contain a two's complement form integer.
1027 * value[0]=0xFF , len=1 -> integer=-1
1028 * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1
1029 * value[0]=0x01 , len=1 -> integer= 1
1030 * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1
1031 * value="123" , len=0 -> integer= 123
1032 * ENUMERATED: as INTEGER (but only with not negative numbers)
1033 * BOOLEAN: VALUE must be the null terminated string "TRUE" or "FALSE" and LEN != 0
1034 * value="TRUE" , len=1 -> boolean=TRUE
1035 * value="FALSE" , len=1 -> boolean=FALSE
1036 * OBJECT IDENTIFIER: VALUE must be a null terminated string with each number separated by
1037 * a blank (e.g. "1 2 3 543 1").
1038 * LEN != 0
1039 * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha
1040 * UTCTime: VALUE must be a null terminated string in one of these formats:
1041 * "YYMMDDhhmmssZ" "YYMMDDhhmmssZ" "YYMMDDhhmmss+hh'mm'" "YYMMDDhhmmss-hh'mm'"
1042 * "YYMMDDhhmm+hh'mm'" "YYMMDDhhmm-hh'mm'".
1043 * LEN != 0
1044 * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 at 12h 00m Greenwich Mean Time
1045 * GeneralizedTime: VALUE must be in one of this format:
1046 * "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.s+hh'mm'"
1047 * "YYYYMMDDhhmmss.s-hh'mm'" "YYYYMMDDhhmm+hh'mm'" "YYYYMMDDhhmm-hh'mm'"
1048 * where ss.s indicates the seconds with any precision like "10.1" or "01.02".
1049 * LEN != 0
1050 * value="2001010112001.12-0700" , len=1 -> time=Jannuary 1st, 2001 at 12h 00m 01.12s
1051 * Pacific Daylight Time
1052 * OCTET STRING: VALUE contains the octet string and LEN is the number of octet.
1053 * value="$\backslash$x01$\backslash$x02$\backslash$x03" , len=3 -> three bytes octet string
1054 * BIT STRING: VALUE contains the bit string organized by bytes and LEN is the number of bits.
1055 * value="$\backslash$xCF" , len=6 -> bit string="110011" (six bits)
1056 * CHOICE: if NAME indicates a choice type, VALUE must specify one of the alternatives with a
1057 * null terminated string. LEN != 0
1058 * Using "pkix.asn":
1059 * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject","rdnSequence",1);
1060 * ANY: VALUE indicates the der encoding of a structure.
1061 * LEN != 0
1062 * SEQUENCE OF: VALUE must be the null terminated string "NEW" and LEN != 0. With this
1063 * instruction another element is appended in the sequence. The name of this
1064 * element will be "?1" if it's the first one, "?2" for the second and so on.
1065 * Using "pkix.asn":
1066 * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1);
1067 * SET OF: the same as SEQUENCE OF.
1068 * Using "pkix.asn":
1069 * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1);
1071 * If an element is OPTIONAL and you want to delete it, you must use the value=NULL and len=0.
1072 * Using "pkix.asn":
1073 * result=asn1_write_value(cert,"certificate1.tbsCertificate.issuerUniqueID",NULL,0);
1076 int
1077 asn1_write_value(node_asn *node_root,char *name,unsigned char *value,int len)
1079 node_asn *node,*p,*p2;
1080 unsigned char *temp,*value_temp,*default_temp;
1081 int len2,k,k2,negative;
1083 node=_asn1_find_node(node_root,name);
1084 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1086 if((node->type & CONST_OPTION) && (value==NULL) && (len==0)){
1087 asn1_delete_structure(node);
1088 return ASN_OK;
1091 switch(type_field(node->type)){
1092 case TYPE_BOOLEAN:
1093 if(!strcmp(value,"TRUE")){
1094 if(node->type&CONST_DEFAULT){
1095 p=node->down;
1096 while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
1097 if(p->type&CONST_TRUE) _asn1_set_value(node,NULL,0);
1098 else _asn1_set_value(node,"T",1);
1100 else _asn1_set_value(node,"T",1);
1102 else if(!strcmp(value,"FALSE")){
1103 if(node->type&CONST_DEFAULT){
1104 p=node->down;
1105 while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
1106 if(p->type&CONST_FALSE) _asn1_set_value(node,NULL,0);
1107 else _asn1_set_value(node,"F",1);
1109 else _asn1_set_value(node,"F",1);
1111 else return ASN_VALUE_NOT_VALID;
1112 break;
1113 case TYPE_INTEGER: case TYPE_ENUMERATED:
1114 if(len==0){
1115 if(isdigit(value[0])){
1116 value_temp=(unsigned char *)gnutls_alloca(4);
1117 if (value_temp==NULL) return ASN_MEM_ERROR;
1119 _asn1_convert_integer(value,value_temp,4, &len);
1121 else{ /* is an identifier like v1 */
1122 if(!(node->type&CONST_LIST)) return ASN_VALUE_NOT_VALID;
1123 p=node->down;
1124 while(p){
1125 if(type_field(p->type)==TYPE_CONSTANT){
1126 if((p->name) && (!strcmp(p->name,value))){
1127 value_temp=(unsigned char *)gnutls_alloca(4);
1128 if (value_temp==NULL) return ASN_MEM_ERROR;
1130 _asn1_convert_integer(p->value,value_temp,4, &len);
1131 break;
1134 p=p->right;
1136 if(p==NULL) return ASN_VALUE_NOT_VALID;
1139 else{
1140 value_temp=(unsigned char *)gnutls_alloca(len);
1141 if (value_temp==NULL) return ASN_MEM_ERROR;
1142 memcpy(value_temp,value,len);
1146 if(value_temp[0]&0x80) negative=1;
1147 else negative=0;
1149 if(negative && (type_field(node->type)==TYPE_ENUMERATED))
1150 {gnutls_afree(value_temp);return ASN_VALUE_NOT_VALID;}
1152 for(k=0;k<len-1;k++)
1153 if(negative && (value_temp[k]!=0xFF)) break;
1154 else if(!negative && value_temp[k]) break;
1156 if((negative && !(value_temp[k]&0x80)) ||
1157 (!negative && (value_temp[k]&0x80))) k--;
1159 _asn1_length_der(len-k,NULL,&len2);
1160 temp=(unsigned char *)gnutls_alloca(len-k+len2);
1161 if (temp==NULL) return ASN_MEM_ERROR;
1163 _asn1_octet_der(value_temp+k,len-k,temp,&len2);
1164 _asn1_set_value(node,temp,len2);
1166 gnutls_afree(temp);
1168 if(node->type&CONST_DEFAULT){
1169 p=node->down;
1170 while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
1171 if(isdigit(p->value[0])){
1172 default_temp=(unsigned char *)gnutls_alloca(4);
1173 if (default_temp==NULL) return ASN_MEM_ERROR;
1175 _asn1_convert_integer(p->value,default_temp,4,&len2);
1177 else{ /* is an identifier like v1 */
1178 if(!(node->type&CONST_LIST)) return ASN_VALUE_NOT_VALID;
1179 p2=node->down;
1180 while(p2){
1181 if(type_field(p2->type)==TYPE_CONSTANT){
1182 if((p2->name) && (!strcmp(p2->name,p->value))){
1183 default_temp=(unsigned char *)gnutls_alloca(4);
1184 if (default_temp==NULL) return ASN_MEM_ERROR;
1186 _asn1_convert_integer(p2->value,default_temp,4,&len2);
1187 break;
1190 p2=p2->right;
1192 if(p2==NULL) return ASN_VALUE_NOT_VALID;
1195 if((len-k)==len2){
1196 for(k2=0;k2<len2;k2++)
1197 if(value_temp[k+k2]!=default_temp[k2]){
1198 break;
1200 if(k2==len2) _asn1_set_value(node,NULL,0);
1202 gnutls_afree(default_temp);
1204 gnutls_afree(value_temp);
1205 break;
1206 case TYPE_OBJECT_ID:
1207 for(k=0;k<strlen(value);k++)
1208 if((!isdigit(value[k])) && (value[k]!=' ') && (value[k]!='+'))
1209 return ASN_VALUE_NOT_VALID;
1210 _asn1_set_value(node,value,strlen(value)+1);
1211 break;
1212 case TYPE_TIME:
1213 if(node->type&CONST_UTC){
1214 if(strlen(value)<11) return ASN_VALUE_NOT_VALID;
1215 for(k=0;k<10;k++)
1216 if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
1217 switch(strlen(value)){
1218 case 11:
1219 if(value[10]!='Z') return ASN_VALUE_NOT_VALID;
1220 break;
1221 case 13:
1222 if((!isdigit(value[10])) || (!isdigit(value[11])) ||
1223 (value[12]!='Z')) return ASN_VALUE_NOT_VALID;
1224 break;
1225 case 15:
1226 if((value[10]!='+') && (value[10]!='-')) return ASN_VALUE_NOT_VALID;
1227 for(k=11;k<15;k++)
1228 if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
1229 break;
1230 case 17:
1231 if((!isdigit(value[10])) || (!isdigit(value[11])))
1232 return ASN_VALUE_NOT_VALID;
1233 if((value[12]!='+') && (value[12]!='-')) return ASN_VALUE_NOT_VALID;
1234 for(k=13;k<17;k++)
1235 if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID;
1236 break;
1237 default:
1238 return ASN_VALUE_NOT_FOUND;
1240 _asn1_set_value(node,value,strlen(value)+1);
1242 else{ /* GENERALIZED TIME */
1243 if(value) _asn1_set_value(node,value,strlen(value)+1);
1245 break;
1246 case TYPE_OCTET_STRING:
1247 _asn1_length_der(len,NULL,&len2);
1248 temp=(unsigned char *)gnutls_alloca(len+len2);
1249 if (temp==NULL) return ASN_MEM_ERROR;
1251 _asn1_octet_der(value,len,temp,&len2);
1252 _asn1_set_value(node,temp,len2);
1253 gnutls_afree(temp);
1254 break;
1255 case TYPE_BIT_STRING:
1256 _asn1_length_der((len>>3)+2,NULL,&len2);
1257 temp=(unsigned char *)gnutls_alloca((len>>3)+2+len2);
1258 if (temp==NULL) return ASN_MEM_ERROR;
1260 _asn1_bit_der(value,len,temp,&len2);
1261 _asn1_set_value(node,temp,len2);
1262 gnutls_afree(temp);
1263 break;
1264 case TYPE_CHOICE:
1265 p=node->down;
1266 while(p){
1267 if(!strcmp(p->name,value)){
1268 p2=node->down;
1269 while(p2){
1270 if(p2!=p){asn1_delete_structure(p2); p2=node->down;}
1271 else p2=p2->right;
1273 break;
1275 p=p->right;
1277 if(!p) return ASN_ELEMENT_NOT_FOUND;
1278 break;
1279 case TYPE_ANY:
1280 _asn1_length_der(len,NULL,&len2);
1281 temp=(unsigned char *)gnutls_alloca(len+len2);
1282 if (temp==NULL) return ASN_MEM_ERROR;
1284 _asn1_octet_der(value,len,temp,&len2);
1285 _asn1_set_value(node,temp,len2);
1286 gnutls_afree(temp);
1287 break;
1288 case TYPE_SEQUENCE_OF: case TYPE_SET_OF:
1289 if(strcmp(value,"NEW")) return ASN_VALUE_NOT_VALID;
1290 _asn1_append_sequence_set(node);
1291 break;
1292 default:
1293 return ASN_ELEMENT_NOT_FOUND;
1294 break;
1297 return ASN_OK;
1300 #define PUT_VALUE( ptr, ptr_size, data, data_size) \
1301 *len = data_size; \
1302 if (ptr_size < data_size) { \
1303 gnutls_assert(); \
1304 return ASN_MEM_ERROR; \
1305 } else { \
1306 memcpy( ptr, data, data_size); \
1309 #define PUT_STR_VALUE( ptr, ptr_size, data) \
1310 *len = strlen(data) + 1; \
1311 if (ptr_size < *len) { \
1312 gnutls_assert(); \
1313 return ASN_MEM_ERROR; \
1314 } else { \
1315 /* this strcpy is checked */ \
1316 strcpy(ptr, data); \
1319 #define ADD_STR_VALUE( ptr, ptr_size, data) \
1320 *len = strlen(data) + 1; \
1321 if (ptr_size < strlen(ptr)+(*len)) { \
1322 gnutls_assert(); \
1323 return ASN_MEM_ERROR; \
1324 } else { \
1325 /* this strcat is checked */ \
1326 strcat(ptr, data); \
1330 * asn1_read_value - Returns the value of one element inside a structure
1331 * @root: pointer to a structure
1332 * @name: the name of the element inside a structure that you want to read.
1333 * @value: vector that will contain the element's content.
1334 * VALUE must be a pointer to memory cells already allocated.
1335 * @len: number of bytes of *value: value[0]..value[len-1]. Initialy holds the sizeof value.
1337 * Description:
1339 * Returns the value of one element inside a structure.
1341 * Returns:
1343 * ASN_OK\: set value OK
1345 * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element.
1347 * ASN_VALUE_NOT_FOUND\: there isn't any value for the element selected.
1349 * Examples:
1350 * a description for each type
1351 * INTEGER: VALUE will contain a two's complement form integer.
1352 * integer=-1 -> value[0]=0xFF , len=1
1353 * integer=1 -> value[0]=0x01 , len=1
1354 * ENUMERATED: as INTEGER (but only with not negative numbers)
1355 * BOOLEAN: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6
1356 * OBJECT IDENTIFIER: VALUE will be a null terminated string with each number separated by
1357 * a blank (i.e. "1 2 3 543 1").
1358 * LEN = strlen(VALUE)+1
1359 * UTCTime: VALUE will be a null terminated string in one of these formats:
1360 * "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'"
1361 * LEN=strlen(VALUE)+1
1362 * GeneralizedTime: VALUE will be a null terminated string in the same format used to set
1363 * the value
1364 * OCTET STRING: VALUE will contain the octet string and LEN will be the number of octet.
1365 * BIT STRING: VALUE will contain the bit string organized by bytes and LEN will be the
1366 * number of bits.
1367 * CHOICE: if NAME indicates a choice type, VALUE will specify the alternative selected
1368 * ANY: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure
1369 * actually used.
1371 * If an element is OPTIONAL and the function "read_value" returns ASN_ELEMENT_NOT_FOUND, it
1372 * means that this element wasn't present in the der encoding that created the structure.
1373 * The first element of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and so on.
1376 int
1377 asn1_read_value(node_asn *root,char *name,unsigned char *value, int *len)
1379 node_asn *node,*p;
1380 int len2,len3;
1381 int value_size = *len;
1383 node=_asn1_find_node(root,name);
1384 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1386 if((type_field(node->type)!=TYPE_NULL) &&
1387 (type_field(node->type)!=TYPE_CHOICE) &&
1388 !(node->type&CONST_DEFAULT) && !(node->type&CONST_ASSIGN) &&
1389 (node->value==NULL))
1390 return ASN_VALUE_NOT_FOUND;
1392 switch(type_field(node->type)){
1393 case TYPE_NULL:
1394 PUT_STR_VALUE( value, value_size, "NULL");
1395 break;
1396 case TYPE_BOOLEAN:
1397 if((node->type&CONST_DEFAULT) && (node->value==NULL)){
1398 p=node->down;
1399 while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
1400 if(p->type&CONST_TRUE) {
1401 PUT_STR_VALUE( value, value_size, "TRUE");
1402 } else {
1403 PUT_STR_VALUE(value, value_size, "FALSE");
1406 else if(node->value[0]=='T') {
1407 PUT_STR_VALUE(value, value_size, "TRUE");
1409 else {
1410 PUT_STR_VALUE(value, value_size, "FALSE");
1412 break;
1413 case TYPE_INTEGER: case TYPE_ENUMERATED:
1414 if((node->type&CONST_DEFAULT) && (node->value==NULL)){
1415 p=node->down;
1416 while(type_field(p->type)!=TYPE_DEFAULT) p=p->right;
1417 if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN_OK) return ASN_MEM_ERROR;
1419 else{
1420 len2=-1;
1421 if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN_OK) return ASN_MEM_ERROR;
1423 break;
1424 case TYPE_OBJECT_ID:
1425 if(node->type&CONST_ASSIGN){
1426 _gnutls_str_cpy(value, *len, "");
1427 p=node->down;
1428 while(p){
1429 if(type_field(p->type)==TYPE_CONSTANT){
1430 ADD_STR_VALUE( value, value_size, p->value);
1431 if(p->right) {
1432 ADD_STR_VALUE( value, value_size, " ");
1435 p=p->right;
1437 } else {
1438 PUT_STR_VALUE(value, value_size, node->value);
1440 break;
1441 case TYPE_TIME:
1442 PUT_STR_VALUE( value, value_size, node->value);
1443 break;
1444 case TYPE_OCTET_STRING:
1445 len2=-1;
1446 if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN_OK) return ASN_MEM_ERROR;
1447 break;
1448 case TYPE_BIT_STRING:
1449 len2=-1;
1450 if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN_OK) return ASN_MEM_ERROR;
1451 break;
1452 case TYPE_CHOICE:
1453 PUT_STR_VALUE( value, value_size, node->down->name);
1454 break;
1455 case TYPE_ANY:
1456 len3=-1;
1457 len2=_asn1_get_length_der(node->value,&len3);
1458 PUT_VALUE( value, value_size, node->value+len3, len2);
1459 break;
1460 default:
1461 return ASN_ELEMENT_NOT_FOUND;
1462 break;
1464 return ASN_OK;
1468 * asn1_number_of_elements - Counts the number of elements of a structure.
1469 * @root: pointer to the root of an ASN1 structure.
1470 * @name: the name of a sub-structure of ROOT.
1471 * @num: pointer to an integer where the result will be stored
1472 * Description:
1474 * Counts the number of elements of a sub-structure called NAME with names equal to "?1","?2", ...
1476 * Returns:
1478 * ASN_OK: creation OK
1479 * ASN_ELEMENT_NOT_FOUND: NAME isn't known
1480 * ASN_GENERIC_ERROR: parameter num equal to NULL
1483 int
1484 asn1_number_of_elements(node_asn *root,char *name,int *num)
1486 node_asn *node,*p;
1488 if(num==NULL) return ASN_GENERIC_ERROR;
1490 *num=0;
1492 node=_asn1_find_node(root,name);
1493 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1495 p=node->down;
1497 while(p){
1498 if((p->name) && (p->name[0]=='?')) (*num)++;
1499 p=p->right;
1502 return ASN_OK;
1506 int
1507 _asn1_set_default_tag(node_asn *node)
1509 node_asn *p;
1511 if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS))
1512 return ASN_ELEMENT_NOT_FOUND;
1514 p=node;
1515 while(p){
1516 if((type_field(p->type)==TYPE_TAG) &&
1517 !(p->type&CONST_EXPLICIT) &&
1518 !(p->type&CONST_IMPLICIT)){
1519 if(node->type&CONST_EXPLICIT) p->type|=CONST_EXPLICIT;
1520 else p->type|=CONST_IMPLICIT;
1523 if(p->down){
1524 p=p->down;
1526 else if(p->right) p=p->right;
1527 else{
1528 while(1){
1529 p=_asn1_find_up(p);
1530 if(p==node){
1531 p=NULL;
1532 break;
1534 if(p->right){
1535 p=p->right;
1536 break;
1542 return ASN_OK;
1546 int
1547 _asn1_check_identifier(node_asn *node)
1549 node_asn *p,*p2;
1550 char name2[129];
1552 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1554 p=node;
1555 while(p){
1556 if(type_field(p->type)==TYPE_IDENTIFIER){
1557 _gnutls_str_cpy(name2, sizeof(name2), node->name);
1558 _gnutls_str_cat(name2, sizeof(name2), ".");
1559 _gnutls_str_cat(name2, sizeof(name2), p->value);
1560 p2=_asn1_find_node(node,name2);
1561 if(p2==NULL){printf("%s\n",name2); return ASN_IDENTIFIER_NOT_FOUND;}
1563 else if((type_field(p->type)==TYPE_OBJECT_ID) &&
1564 (p->type&CONST_ASSIGN)){
1565 p2=p->down;
1566 if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
1567 if(p2->value && !isdigit(p2->value[0])){
1568 _gnutls_str_cpy(name2, sizeof(name2), node->name);
1569 _gnutls_str_cat(name2, sizeof(name2), ".");
1570 _gnutls_str_cat(name2, sizeof(name2), p2->value);
1571 p2=_asn1_find_node(node,name2);
1572 if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
1573 !(p2->type&CONST_ASSIGN))
1574 {printf("%s\n",name2); return ASN_IDENTIFIER_NOT_FOUND;}
1579 if(p->down){
1580 p=p->down;
1582 else if(p->right) p=p->right;
1583 else{
1584 while(1){
1585 p=_asn1_find_up(p);
1586 if(p==node){
1587 p=NULL;
1588 break;
1590 if(p->right){
1591 p=p->right;
1592 break;
1598 return ASN_OK;
1602 int
1603 _asn1_change_integer_value(node_asn *node)
1605 node_asn *p;
1606 unsigned char val[4],val2[5];
1607 int len;
1609 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1611 p=node;
1612 while(p){
1613 if((type_field(p->type)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){
1614 if(p->value){
1615 _asn1_convert_integer(p->value,val,sizeof(val), &len);
1616 _asn1_octet_der(val,len,val2,&len);
1617 _asn1_set_value(p,val2,len);
1621 if(p->down){
1622 p=p->down;
1624 else{
1625 if(p==node) p=NULL;
1626 else if(p->right) p=p->right;
1627 else{
1628 while(1){
1629 p=_asn1_find_up(p);
1630 if(p==node){
1631 p=NULL;
1632 break;
1634 if(p->right){
1635 p=p->right;
1636 break;
1643 return ASN_OK;
1647 int
1648 _asn1_delete_not_used(node_asn *node)
1650 node_asn *p,*p2;
1652 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1654 p=node;
1655 while(p){
1656 if(p->type&CONST_NOT_USED){
1657 p2=NULL;
1658 if(p!=node){
1659 p2=_asn1_find_left(p);
1660 if(!p2) p2=_asn1_find_up(p);
1662 asn1_delete_structure(p);
1663 p=p2;
1666 if(!p) break; /* reach node */
1668 if(p->down){
1669 p=p->down;
1671 else{
1672 if(p==node) p=NULL;
1673 else if(p->right) p=p->right;
1674 else{
1675 while(1){
1676 p=_asn1_find_up(p);
1677 if(p==node){
1678 p=NULL;
1679 break;
1681 if(p->right){
1682 p=p->right;
1683 break;
1689 return ASN_OK;
1694 int
1695 _asn1_expand_identifier(node_asn **node,node_asn *root)
1697 node_asn *p,*p2,*p3;
1698 char name2[129];
1699 int move;
1701 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1703 p=*node;
1704 move=DOWN;
1706 while(!((p==*node) && (move==UP))){
1707 if(move!=UP){
1708 if(type_field(p->type)==TYPE_IDENTIFIER){
1709 _gnutls_str_cpy(name2, sizeof(name2), root->name);
1710 _gnutls_str_cat(name2, sizeof(name2), ".");
1711 _gnutls_str_cat(name2, sizeof(name2), p->value);
1712 p2=_asn1_copy_structure2(root,name2);
1713 if(p2==NULL) return ASN_IDENTIFIER_NOT_FOUND;
1714 _asn1_set_name(p2,p->name);
1715 p2->right=p->right;
1716 p2->left=p->left;
1717 if(p->right) p->right->left=p2;
1718 p3=p->down;
1719 if(p3){
1720 while(p3->right) p3=p3->right;
1721 _asn1_set_right(p3,p2->down);
1722 _asn1_set_down(p2,p->down);
1725 p3=_asn1_find_left(p);
1726 if(p3) _asn1_set_right(p3,p2);
1727 else{
1728 p3=_asn1_find_up(p);
1729 if(p3) _asn1_set_down(p3,p2);
1730 else {
1731 p2->left=NULL;
1735 if(p->type & CONST_SIZE) p2->type|=CONST_SIZE;
1736 if(p->type & CONST_TAG) p2->type|=CONST_TAG;
1737 if(p->type & CONST_OPTION) p2->type|=CONST_OPTION;
1738 if(p->type & CONST_DEFAULT) p2->type|=CONST_DEFAULT;
1739 if(p->type & CONST_SET) p2->type|=CONST_SET;
1740 if(p->type & CONST_NOT_USED) p2->type|=CONST_NOT_USED;
1742 if(p==*node) *node=p2;
1743 _asn1_remove_node(p);
1744 p=p2;
1745 move=DOWN;
1746 continue;
1748 move=DOWN;
1750 else move=RIGHT;
1752 if(move==DOWN){
1753 if(p->down) p=p->down;
1754 else move=RIGHT;
1757 if(p==*node) {move=UP; continue;}
1759 if(move==RIGHT){
1760 if(p->right) p=p->right;
1761 else move=UP;
1763 if(move==UP) p=_asn1_find_up(p);
1766 return ASN_OK;
1771 int
1772 _asn1_type_choice_config(node_asn *node)
1774 node_asn *p,*p2,*p3,*p4;
1775 int move;
1777 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1779 p=node;
1780 move=DOWN;
1782 while(!((p==node) && (move==UP))){
1783 if(move!=UP){
1784 if((type_field(p->type)==TYPE_CHOICE) &&
1785 (p->type&CONST_TAG)){
1786 p2=p->down;
1787 while(p2){
1788 if(type_field(p2->type)!=TYPE_TAG){
1789 p2->type|=CONST_TAG;
1790 p3=_asn1_find_left(p2);
1791 while(p3){
1792 if(type_field(p3->type)==TYPE_TAG){
1793 p4=_asn1_add_node(p3->type);
1794 _asn1_set_value(p4,p3->value,strlen(p3->value)+1);
1795 _asn1_set_right(p4,p2->down);
1796 _asn1_set_down(p2,p4);
1798 p3=_asn1_find_left(p3);
1801 p2=p2->right;
1803 p->type&=~(CONST_TAG);
1804 p2=p->down;
1805 while(p2){
1806 p3=p2->right;
1807 if(type_field(p2->type)==TYPE_TAG) asn1_delete_structure(p2);
1808 p2=p3;
1811 move=DOWN;
1813 else move=RIGHT;
1815 if(move==DOWN){
1816 if(p->down) p=p->down;
1817 else move=RIGHT;
1820 if(p==node) {move=UP; continue;}
1822 if(move==RIGHT){
1823 if(p->right) p=p->right;
1824 else move=UP;
1826 if(move==UP) p=_asn1_find_up(p);
1829 return ASN_OK;
1833 int
1834 _asn1_type_set_config(node_asn *node)
1836 node_asn *p,*p2;
1837 int move;
1839 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1841 p=node;
1842 move=DOWN;
1844 while(!((p==node) && (move==UP))){
1845 if(move!=UP){
1846 if(type_field(p->type)==TYPE_SET){
1847 p2=p->down;
1848 while(p2){
1849 if(type_field(p2->type)!=TYPE_TAG)
1850 p2->type|=CONST_SET|CONST_NOT_USED;
1851 p2=p2->right;
1854 move=DOWN;
1856 else move=RIGHT;
1858 if(move==DOWN){
1859 if(p->down) p=p->down;
1860 else move=RIGHT;
1863 if(p==node) {move=UP; continue;}
1865 if(move==RIGHT){
1866 if(p->right) p=p->right;
1867 else move=UP;
1869 if(move==UP) p=_asn1_find_up(p);
1872 return ASN_OK;
1876 int
1877 _asn1_expand_object_id(node_asn *node)
1879 node_asn *p,*p2,*p3,*p4,*p5;
1880 char name_root[129],name2[129];
1881 int move;
1883 if(node==NULL) return ASN_ELEMENT_NOT_FOUND;
1885 _gnutls_str_cpy(name_root, sizeof(name_root), node->name);
1887 p=node;
1888 move=DOWN;
1890 while(!((p==node) && (move==UP))){
1891 if(move!=UP){
1892 if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){
1893 p2=p->down;
1894 if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
1895 if(p2->value && !isdigit(p2->value[0])){
1896 _gnutls_str_cpy(name2, sizeof(name2), name_root);
1897 _gnutls_str_cat(name2, sizeof(name2), ".");
1898 _gnutls_str_cat(name2, sizeof(name2), p2->value);
1899 p3=_asn1_find_node(node,name2);
1900 if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) ||
1901 !(p3->type&CONST_ASSIGN)) return ASN_ELEMENT_NOT_FOUND;
1902 _asn1_set_down(p,p2->right);
1903 _asn1_remove_node(p2);
1904 p2=p;
1905 p4=p3->down;
1906 while(p4){
1907 if(type_field(p4->type)==TYPE_CONSTANT){
1908 p5=_asn1_add_node(TYPE_CONSTANT);
1909 _asn1_set_name(p5,p4->name);
1910 _asn1_set_value(p5,p4->value,strlen(p4->value)+1);
1911 if(p2==p){
1912 _asn1_set_right(p5,p->down);
1913 _asn1_set_down(p,p5);
1915 else{
1916 _asn1_set_right(p5,p2->right);
1917 _asn1_set_right(p2,p5);
1919 p2=p5;
1921 p4=p4->right;
1923 move=DOWN;
1924 continue;
1928 move=DOWN;
1930 else move=RIGHT;
1932 if(move==DOWN){
1933 if(p->down) p=p->down;
1934 else move=RIGHT;
1937 if(p==node) {move=UP; continue;}
1939 if(move==RIGHT){
1940 if(p->right) p=p->right;
1941 else move=UP;
1943 if(move==UP) p=_asn1_find_up(p);
1946 return ASN_OK;