2 * Copyright (C) 2002 Fabio Fiorina
4 * This file is part of LIBASN1.
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.
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
22 /*****************************************************/
23 /* File: structure.c */
24 /* Description: Functions to create and delete an */
26 /*****************************************************/
31 #include <structure.h>
32 #include "parser_aux.h"
37 extern char _asn1_identifierMissing
[];
40 /******************************************************/
41 /* Function : _asn1_add_node_only */
42 /* Description: creates a new NODE_ASN element. */
44 /* type: type of the new element (see TYPE_ */
45 /* and CONST_ constants). */
46 /* Return: pointer to the new element. */
47 /******************************************************/
49 _asn1_add_node_only(unsigned int type
)
53 punt
=(node_asn
*) _asn1_malloc(sizeof(node_asn
));
54 if (punt
==NULL
) return NULL
;
67 /******************************************************************/
68 /* Function : _asn1_find_left */
69 /* Description: returns the NODE_ASN element with RIGHT field that*/
70 /* points the element NODE. */
72 /* node: NODE_ASN element pointer. */
73 /* Return: NULL if not found. */
74 /******************************************************************/
76 _asn1_find_left(node_asn
*node
)
78 if((node
==NULL
) || (node
->left
==NULL
) ||
79 (node
->left
->down
==node
)) return NULL
;
86 _asn1_create_static_structure(ASN1_TYPE pointer
,char* output_file_name
,char *vector_name
)
92 file
=fopen( output_file_name
,"w");
94 if(file
==NULL
) return ASN1_FILE_NOT_FOUND
;
96 fprintf(file
,"\n#include \"libtasn1.h\"\n\n");
97 fprintf(file
,"const ASN1_ARRAY_TYPE %s[]={\n",vector_name
);
104 if(p
->name
) fprintf(file
,"\"%s\",",p
->name
);
105 else fprintf(file
,"0,");
108 if(p
->down
) t
|=CONST_DOWN
;
109 if(p
->right
) t
|=CONST_RIGHT
;
111 fprintf(file
,"%lu,",t
);
113 if(p
->value
) fprintf(file
,"\"%s\"},\n",p
->value
);
114 else fprintf(file
,"0},\n");
137 fprintf(file
," {0,0,0}\n};\n");
146 * asn1_array2tree - Creates the structures needed to manage the ASN1 definitions.
147 * @array: specify the array that contains ASN.1 declarations
148 * @definitions: return the pointer to the structure created by *ARRAY ASN.1 declarations
149 * @errorDescription : return the error description.
152 * Creates the structures needed to manage the ASN1 definitions. ARRAY is a vector created by
153 * 'asn1_parser_asn1_file_c' function.
157 * ASN1_SUCCESS\: structure created correctly.
159 * ASN1_ELEMENT_NOT_EMPTY\: *DEFINITIONS not ASN1_TYPE_EMPTY
161 * ASN1_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined (see ERRORDESCRIPTION for more information).
163 * ASN1_ARRAY_ERROR\: the array pointed by ARRAY is wrong.
166 asn1_array2tree(const ASN1_ARRAY_TYPE
*array
,ASN1_TYPE
*definitions
,
167 char *errorDescription
)
169 node_asn
*p
,*p_last
=NULL
;
175 if(*definitions
!= ASN1_TYPE_EMPTY
)
176 return ASN1_ELEMENT_NOT_EMPTY
;
181 while(array
[k
].value
|| array
[k
].type
|| array
[k
].name
){
182 p
=_asn1_add_node(array
[k
].type
&(~CONST_DOWN
));
183 if(array
[k
].name
) _asn1_set_name(p
,array
[k
].name
);
184 if(array
[k
].value
) _asn1_set_value(p
,array
[k
].value
,
185 strlen(array
[k
].value
)+1);
187 if(*definitions
==NULL
) *definitions
=p
;
189 if(move
==DOWN
) _asn1_set_down(p_last
,p
);
190 else if(move
==RIGHT
) _asn1_set_right(p_last
,p
);
194 if(array
[k
].type
&CONST_DOWN
) move
=DOWN
;
195 else if(array
[k
].type
&CONST_RIGHT
) move
=RIGHT
;
198 if(p_last
==*definitions
) break;
200 p_last
= _asn1_find_up(p_last
);
202 if(p_last
==NULL
) break;
204 if(p_last
->type
&CONST_RIGHT
){
205 p_last
->type
&=~CONST_RIGHT
;
214 if(p_last
==*definitions
){
215 result
=_asn1_check_identifier(*definitions
);
216 if(result
==ASN1_SUCCESS
){
217 _asn1_change_integer_value(*definitions
);
218 _asn1_expand_object_id(*definitions
);
222 result
=ASN1_ARRAY_ERROR
;
225 if (errorDescription
!=NULL
) {
226 if(result
==ASN1_IDENTIFIER_NOT_FOUND
) {
227 Estrcpy(errorDescription
,":: identifier '");
228 Estrcat(errorDescription
,_asn1_identifierMissing
);
229 Estrcat(errorDescription
,"' not found");
232 errorDescription
[0]=0;
235 if(result
!= ASN1_SUCCESS
){
236 _asn1_delete_list_and_nodes();
237 *definitions
=ASN1_TYPE_EMPTY
;
247 * asn1_delete_structure - Deletes the structure pointed by *ROOT.
248 * @structure: pointer to the structure that you want to delete.
251 * Deletes the structure *ROOT.
252 * At the end *ROOT is setted to ASN1_TYPE_EMPTY.
256 * ASN1_SUCCESS\: everything OK
258 * ASN1_ELEMENT_NOT_FOUND\: *root==ASN1_TYPE_EMPTY.
262 asn1_delete_structure(ASN1_TYPE
*structure
)
266 if(*structure
==ASN1_TYPE_EMPTY
) return ASN1_ELEMENT_NOT_FOUND
;
277 _asn1_set_down(p3
,p2
);
278 _asn1_remove_node(p
);
282 p3
=_asn1_find_left(p
);
285 if(p3
) _asn1_set_down(p3
,p2
);
287 if(p
->right
) p
->right
->left
=NULL
;
290 else _asn1_set_right(p3
,p2
);
291 _asn1_remove_node(p
);
297 *structure
=ASN1_TYPE_EMPTY
;
304 _asn1_copy_structure3(node_asn
*source_node
)
306 node_asn
*dest_node
,*p_s
,*p_d
,*p_d_prev
;
309 if(source_node
==NULL
) return NULL
;
311 dest_node
=_asn1_add_node_only(source_node
->type
);
320 if(p_s
->name
) _asn1_set_name(p_d
,p_s
->name
);
322 switch(type_field(p_s
->type
)){
323 case TYPE_OCTET_STRING
: case TYPE_BIT_STRING
: case TYPE_GENERALSTRING
:
326 len
=_asn1_get_length_der(p_s
->value
,&len2
);
327 _asn1_set_value(p_d
,p_s
->value
,len
+len2
);
330 _asn1_set_value(p_d
,p_s
->value
,strlen(p_s
->value
)+1);
341 p_d
=_asn1_add_node_only(p_s
->type
);
342 _asn1_set_down(p_d_prev
,p_d
);
347 if(p_s
==source_node
) break;
353 p_d
=_asn1_add_node_only(p_s
->type
);
354 _asn1_set_right(p_d_prev
,p_d
);
359 p_s
=_asn1_find_up(p_s
);
360 p_d
=_asn1_find_up(p_d
);
362 }while(p_s
!=source_node
);
369 _asn1_copy_structure2(node_asn
*root
,const char *source_name
)
371 node_asn
*source_node
;
373 source_node
=_asn1_find_node(root
,source_name
);
375 return _asn1_copy_structure3(source_node
);
381 _asn1_type_choice_config(node_asn
*node
)
383 node_asn
*p
,*p2
,*p3
,*p4
;
386 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
391 while(!((p
==node
) && (move
==UP
))){
393 if((type_field(p
->type
)==TYPE_CHOICE
) &&
394 (p
->type
&CONST_TAG
)){
397 if(type_field(p2
->type
)!=TYPE_TAG
){
399 p3
=_asn1_find_left(p2
);
401 if(type_field(p3
->type
)==TYPE_TAG
){
402 p4
=_asn1_add_node_only(p3
->type
);
403 _asn1_set_value(p4
,p3
->value
,strlen(p3
->value
)+1);
404 _asn1_set_right(p4
,p2
->down
);
405 _asn1_set_down(p2
,p4
);
407 p3
=_asn1_find_left(p3
);
412 p
->type
&=~(CONST_TAG
);
416 if(type_field(p2
->type
)==TYPE_TAG
) asn1_delete_structure(&p2
);
425 if(p
->down
) p
=p
->down
;
429 if(p
==node
) {move
=UP
; continue;}
432 if(p
->right
) p
=p
->right
;
435 if(move
==UP
) p
=_asn1_find_up(p
);
443 _asn1_expand_identifier(node_asn
**node
,node_asn
*root
)
446 char name2
[MAX_NAME_SIZE
+2];
449 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
454 while(!((p
==*node
) && (move
==UP
))){
456 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
457 _asn1_str_cpy(name2
, sizeof(name2
), root
->name
);
458 _asn1_str_cat(name2
, sizeof(name2
), ".");
459 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
460 p2
=_asn1_copy_structure2(root
,name2
);
462 return ASN1_IDENTIFIER_NOT_FOUND
;
464 _asn1_set_name(p2
,p
->name
);
467 if(p
->right
) p
->right
->left
=p2
;
470 while(p3
->right
) p3
=p3
->right
;
471 _asn1_set_right(p3
,p2
->down
);
472 _asn1_set_down(p2
,p
->down
);
475 p3
=_asn1_find_left(p
);
476 if(p3
) _asn1_set_right(p3
,p2
);
479 if(p3
) _asn1_set_down(p3
,p2
);
485 if(p
->type
& CONST_SIZE
) p2
->type
|=CONST_SIZE
;
486 if(p
->type
& CONST_TAG
) p2
->type
|=CONST_TAG
;
487 if(p
->type
& CONST_OPTION
) p2
->type
|=CONST_OPTION
;
488 if(p
->type
& CONST_DEFAULT
) p2
->type
|=CONST_DEFAULT
;
489 if(p
->type
& CONST_SET
) p2
->type
|=CONST_SET
;
490 if(p
->type
& CONST_NOT_USED
) p2
->type
|=CONST_NOT_USED
;
492 if(p
==*node
) *node
=p2
;
493 _asn1_remove_node(p
);
503 if(p
->down
) p
=p
->down
;
507 if(p
==*node
) {move
=UP
; continue;}
510 if(p
->right
) p
=p
->right
;
513 if(move
==UP
) p
=_asn1_find_up(p
);
521 * asn1_create_element - Creates a structure of type SOURCE_NAME.
522 * @definitions: pointer to the structure returned by "parser_asn1" function
523 * @source_name: the name of the type of the new structure (must be inside p_structure).
524 * @element: pointer to the structure created.
527 * Creates a structure called DEST_NAME of type SOURCE_NAME.
531 * ASN1_SUCCESS\: creation OK
533 * ASN1_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known
535 * Example: using "pkix.asn"
536 * result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert);
539 asn1_create_element(ASN1_TYPE definitions
,const char *source_name
,
545 dest_node
=_asn1_copy_structure2(definitions
,source_name
);
547 if(dest_node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
549 _asn1_set_name(dest_node
,"");
551 res
=_asn1_expand_identifier(&dest_node
,definitions
);
552 _asn1_type_choice_config(dest_node
);
561 * asn1_print_structure - Prints on the standard output the structure's tree
562 * @out: pointer to the output file (e.g. stdout).
563 * @structure: pointer to the structure that you want to visit.
564 * @name: an element of the structure
566 * Prints on the standard output the structure's tree starting from the NAME element inside
567 * the structure *POINTER.
570 asn1_print_structure(FILE *out
,ASN1_TYPE structure
,const char *name
,int mode
)
573 int k
,indent
=0,len
,len2
,len3
;
575 if(out
==NULL
) return;
577 root
=_asn1_find_node(structure
,name
);
579 if(root
==NULL
) return;
583 if(mode
== ASN1_PRINT_ALL
){
584 for(k
=0;k
<indent
;k
++)fprintf(out
," ");
585 fprintf(out
,"name:");
586 if(p
->name
) fprintf(out
,"%s ",p
->name
);
587 else fprintf(out
,"NULL ");
590 switch(type_field(p
->type
)){
596 for(k
=0;k
<indent
;k
++)fprintf(out
," ");
597 fprintf(out
,"name:");
598 if(p
->name
) fprintf(out
,"%s ",p
->name
);
599 else fprintf(out
,"NULL ");
603 if(mode
!= ASN1_PRINT_NAME
){
604 switch(type_field(p
->type
)){
606 if(mode
== ASN1_PRINT_ALL
)
607 fprintf(out
,"type:CONST");break;
609 if(mode
== ASN1_PRINT_ALL
)
610 fprintf(out
,"type:TAG");break;
612 if(mode
== ASN1_PRINT_ALL
)
613 fprintf(out
,"type:SIZE");break;
615 fprintf(out
,"type:DEFAULT");break;
617 fprintf(out
,"type:NULL");break;
618 case TYPE_IDENTIFIER
:
619 fprintf(out
,"type:IDENTIFIER");break;
621 fprintf(out
,"type:INTEGER");break;
622 case TYPE_ENUMERATED
:
623 fprintf(out
,"type:ENUMERATED");break;
625 fprintf(out
,"type:TIME");break;
627 fprintf(out
,"type:BOOLEAN");break;
629 fprintf(out
,"type:SEQUENCE");break;
630 case TYPE_BIT_STRING
:
631 fprintf(out
,"type:BIT_STR");break;
632 case TYPE_OCTET_STRING
:
633 fprintf(out
,"type:OCT_STR");break;
634 case TYPE_GENERALSTRING
:
635 fprintf(out
,"type:GENERALSTRING");break;
636 case TYPE_SEQUENCE_OF
:
637 fprintf(out
,"type:SEQ_OF");break;
639 fprintf(out
,"type:OBJ_ID");break;
641 fprintf(out
,"type:ANY");break;
643 fprintf(out
,"type:SET");break;
645 fprintf(out
,"type:SET_OF");break;
647 fprintf(out
,"type:CHOICE");break;
648 case TYPE_DEFINITIONS
:
649 fprintf(out
,"type:DEFINITIONS");break;
655 if((mode
== ASN1_PRINT_NAME_TYPE_VALUE
) ||
656 (mode
== ASN1_PRINT_ALL
)){
657 switch(type_field(p
->type
)){
659 if(mode
== ASN1_PRINT_ALL
)
660 if(p
->value
) fprintf(out
," value:%s",p
->value
);
663 if(mode
== ASN1_PRINT_ALL
)
664 fprintf(out
," value:%s",p
->value
);
667 if(mode
== ASN1_PRINT_ALL
)
668 if(p
->value
) fprintf(out
," value:%s",p
->value
);
671 if(p
->value
) fprintf(out
," value:%s",p
->value
);
672 else if(p
->type
& CONST_TRUE
) fprintf(out
," value:TRUE");
673 else if(p
->type
& CONST_FALSE
) fprintf(out
," value:FALSE");
675 case TYPE_IDENTIFIER
:
676 if(p
->value
) fprintf(out
," value:%s",p
->value
);
681 len
=_asn1_get_length_der(p
->value
,&len2
);
682 fprintf(out
," value:0x");
683 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
686 case TYPE_ENUMERATED
:
689 len
=_asn1_get_length_der(p
->value
,&len2
);
690 fprintf(out
," value:0x");
691 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
695 if(p
->value
) fprintf(out
," value:%s",p
->value
);
699 if(p
->value
[0]=='T') fprintf(out
," value:TRUE");
700 else if(p
->value
[0]=='F') fprintf(out
," value:FALSE");
703 case TYPE_BIT_STRING
:
706 len
=_asn1_get_length_der(p
->value
,&len2
);
707 fprintf(out
," value(%i):",(len
-1)*8-(p
->value
[len2
]));
708 for(k
=1;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
711 case TYPE_OCTET_STRING
:
714 len
=_asn1_get_length_der(p
->value
,&len2
);
715 fprintf(out
," value:");
716 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
719 case TYPE_GENERALSTRING
:
722 len
=_asn1_get_length_der(p
->value
,&len2
);
723 fprintf(out
," value:");
724 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
728 if(p
->value
) fprintf(out
," value:%s",p
->value
);
733 len2
=_asn1_get_length_der(p
->value
,&len3
);
734 fprintf(out
," value:");
735 for(k
=0;k
<len2
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len3
]);
741 case TYPE_DEFINITIONS
:
742 case TYPE_SEQUENCE_OF
:
751 if(mode
==ASN1_PRINT_ALL
){
752 if(p
->type
&0x1FFFFF00){
753 fprintf(out
," attr:");
754 if(p
->type
& CONST_UNIVERSAL
) fprintf(out
,"UNIVERSAL,");
755 if(p
->type
& CONST_PRIVATE
) fprintf(out
,"PRIVATE,");
756 if(p
->type
& CONST_APPLICATION
) fprintf(out
,"APPLICATION,");
757 if(p
->type
& CONST_EXPLICIT
) fprintf(out
,"EXPLICIT,");
758 if(p
->type
& CONST_IMPLICIT
) fprintf(out
,"IMPLICIT,");
759 if(p
->type
& CONST_TAG
) fprintf(out
,"TAG,");
760 if(p
->type
& CONST_DEFAULT
) fprintf(out
,"DEFAULT,");
761 if(p
->type
& CONST_TRUE
) fprintf(out
,"TRUE,");
762 if(p
->type
& CONST_FALSE
) fprintf(out
,"FALSE,");
763 if(p
->type
& CONST_LIST
) fprintf(out
,"LIST,");
764 if(p
->type
& CONST_MIN_MAX
) fprintf(out
,"MIN_MAX,");
765 if(p
->type
& CONST_OPTION
) fprintf(out
,"OPTION,");
766 if(p
->type
& CONST_1_PARAM
) fprintf(out
,"1_PARAM,");
767 if(p
->type
& CONST_SIZE
) fprintf(out
,"SIZE,");
768 if(p
->type
& CONST_DEFINED_BY
) fprintf(out
,"DEF_BY,");
769 if(p
->type
& CONST_GENERALIZED
) fprintf(out
,"GENERALIZED,");
770 if(p
->type
& CONST_UTC
) fprintf(out
,"UTC,");
771 if(p
->type
& CONST_SET
) fprintf(out
,"SET,");
772 if(p
->type
& CONST_NOT_USED
) fprintf(out
,"NOT_USED,");
773 if(p
->type
& CONST_ASSIGN
) fprintf(out
,"ASSIGNMENT,");
777 if(mode
== ASN1_PRINT_ALL
){
781 switch(type_field(p
->type
)){
799 else if(p
->right
) p
=p
->right
;
820 * asn1_number_of_elements - Counts the number of elements of a structure.
821 * @element: pointer to the root of an ASN1 structure.
822 * @name: the name of a sub-structure of ROOT.
823 * @num: pointer to an integer where the result will be stored
826 * Counts the number of elements of a sub-structure called NAME with names equal to "?1","?2", ...
830 * ASN1_SUCCESS\: creation OK
831 * ASN1_ELEMENT_NOT_FOUND\: NAME isn't known
832 * ASN1_GENERIC_ERROR\: pointer num equal to NULL
836 asn1_number_of_elements(ASN1_TYPE element
,const char *name
,int *num
)
840 if(num
==NULL
) return ASN1_GENERIC_ERROR
;
844 node
=_asn1_find_node(element
,name
);
845 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
850 if((p
->name
) && (p
->name
[0]=='?')) (*num
)++;
859 * asn1_find_structure_from_oid - Search the structure that is defined just
860 * after an OID definition.
861 * @definitions: ASN1 definitions
862 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
865 * Search the structure that is defined just after an OID definition.
869 * NULL when OIDVALUE not found,
871 * otherwise the pointer to a constant string that contains the element
872 * name defined just after the OID.
876 asn1_find_structure_from_oid(ASN1_TYPE definitions
,
877 const char *oidValue
)
879 char definitionsName
[MAX_NAME_SIZE
],name
[2*MAX_NAME_SIZE
+1];
880 char value
[MAX_NAME_SIZE
];
885 if((definitions
==ASN1_TYPE_EMPTY
) || (oidValue
==NULL
))
886 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
889 strcpy(definitionsName
,definitions
->name
);
890 strcat(definitionsName
,".");
892 /* search the OBJECT_ID into definitions */
895 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
896 (p
->type
& CONST_ASSIGN
)){
897 strcpy(name
,definitionsName
);
898 strcat(name
,p
->name
);
901 result
=asn1_read_value(definitions
,name
,value
,&len
);
903 if((result
== ASN1_SUCCESS
) && (!strcmp(oidValue
,value
))){
905 if(p
==NULL
) /* reach the end of ASN1 definitions */
906 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
914 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */