2 * Copyright (C) 2002 Fabio Fiorina
3 * Copyright (C) 2004 Simon Josefsson
5 * This file is part of LIBASN1.
7 * The LIBTASN1 library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 /*****************************************************/
24 /* File: structure.c */
25 /* Description: Functions to create and delete an */
27 /*****************************************************/
32 #include <structure.h>
33 #include "parser_aux.h"
38 extern char _asn1_identifierMissing
[];
41 /******************************************************/
42 /* Function : _asn1_add_node_only */
43 /* Description: creates a new NODE_ASN element. */
45 /* type: type of the new element (see TYPE_ */
46 /* and CONST_ constants). */
47 /* Return: pointer to the new element. */
48 /******************************************************/
50 _asn1_add_node_only(unsigned int type
)
54 punt
=(node_asn
*) _asn1_malloc(sizeof(node_asn
));
55 if (punt
==NULL
) return NULL
;
68 /******************************************************************/
69 /* Function : _asn1_find_left */
70 /* Description: returns the NODE_ASN element with RIGHT field that*/
71 /* points the element NODE. */
73 /* node: NODE_ASN element pointer. */
74 /* Return: NULL if not found. */
75 /******************************************************************/
77 _asn1_find_left(node_asn
*node
)
79 if((node
==NULL
) || (node
->left
==NULL
) ||
80 (node
->left
->down
==node
)) return NULL
;
87 _asn1_create_static_structure(ASN1_TYPE pointer
,char* output_file_name
,char *vector_name
)
93 file
=fopen( output_file_name
,"w");
95 if(file
==NULL
) return ASN1_FILE_NOT_FOUND
;
97 fprintf(file
,"\n#include \"libtasn1.h\"\n\n");
98 fprintf(file
,"const ASN1_ARRAY_TYPE %s[]={\n",vector_name
);
105 if(p
->name
) fprintf(file
,"\"%s\",",p
->name
);
106 else fprintf(file
,"0,");
109 if(p
->down
) t
|=CONST_DOWN
;
110 if(p
->right
) t
|=CONST_RIGHT
;
112 fprintf(file
,"%lu,",t
);
114 if(p
->value
) fprintf(file
,"\"%s\"},\n",p
->value
);
115 else fprintf(file
,"0},\n");
138 fprintf(file
," {0,0,0}\n};\n");
147 * asn1_array2tree - Creates the structures needed to manage the ASN1 definitions.
148 * @array: specify the array that contains ASN.1 declarations
149 * @definitions: return the pointer to the structure created by
150 * *ARRAY ASN.1 declarations
151 * @errorDescription: return the error description.
153 * Creates the structures needed to manage the ASN.1 definitions.
154 * @array is a vector created by asn1_parser2array().
158 * ASN1_SUCCESS: Structure created correctly.
160 * ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
162 * ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
163 * is not defined (see @errorDescription for more information).
165 * ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
168 asn1_array2tree(const ASN1_ARRAY_TYPE
*array
,ASN1_TYPE
*definitions
,
169 char *errorDescription
)
171 node_asn
*p
,*p_last
=NULL
;
177 if(*definitions
!= ASN1_TYPE_EMPTY
)
178 return ASN1_ELEMENT_NOT_EMPTY
;
183 while(array
[k
].value
|| array
[k
].type
|| array
[k
].name
){
184 p
=_asn1_add_node(array
[k
].type
&(~CONST_DOWN
));
185 if(array
[k
].name
) _asn1_set_name(p
,array
[k
].name
);
186 if(array
[k
].value
) _asn1_set_value(p
,array
[k
].value
,
187 strlen(array
[k
].value
)+1);
189 if(*definitions
==NULL
) *definitions
=p
;
191 if(move
==DOWN
) _asn1_set_down(p_last
,p
);
192 else if(move
==RIGHT
) _asn1_set_right(p_last
,p
);
196 if(array
[k
].type
&CONST_DOWN
) move
=DOWN
;
197 else if(array
[k
].type
&CONST_RIGHT
) move
=RIGHT
;
200 if(p_last
==*definitions
) break;
202 p_last
= _asn1_find_up(p_last
);
204 if(p_last
==NULL
) break;
206 if(p_last
->type
&CONST_RIGHT
){
207 p_last
->type
&=~CONST_RIGHT
;
216 if(p_last
==*definitions
){
217 result
=_asn1_check_identifier(*definitions
);
218 if(result
==ASN1_SUCCESS
){
219 _asn1_change_integer_value(*definitions
);
220 _asn1_expand_object_id(*definitions
);
224 result
=ASN1_ARRAY_ERROR
;
227 if (errorDescription
!=NULL
) {
228 if(result
==ASN1_IDENTIFIER_NOT_FOUND
) {
229 Estrcpy(errorDescription
,":: identifier '");
230 Estrcat(errorDescription
,_asn1_identifierMissing
);
231 Estrcat(errorDescription
,"' not found");
234 errorDescription
[0]=0;
237 if(result
!= ASN1_SUCCESS
){
238 _asn1_delete_list_and_nodes();
239 *definitions
=ASN1_TYPE_EMPTY
;
249 * asn1_delete_structure - Deletes the structure pointed by *ROOT.
250 * @structure: pointer to the structure that you want to delete.
252 * Deletes the structure *@structure. At the end, *@structure is set
253 * to ASN1_TYPE_EMPTY.
257 * ASN1_SUCCESS: Everything OK.
259 * ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
263 asn1_delete_structure(ASN1_TYPE
*structure
)
267 if(*structure
==ASN1_TYPE_EMPTY
) return ASN1_ELEMENT_NOT_FOUND
;
278 _asn1_set_down(p3
,p2
);
279 _asn1_remove_node(p
);
283 p3
=_asn1_find_left(p
);
286 if(p3
) _asn1_set_down(p3
,p2
);
288 if(p
->right
) p
->right
->left
=NULL
;
291 else _asn1_set_right(p3
,p2
);
292 _asn1_remove_node(p
);
298 *structure
=ASN1_TYPE_EMPTY
;
304 * asn1_delete_element - Deletes the element of a structure.
305 * @structure: pointer to the structure that contains the element you
307 * @element_name: element's name you want to delete.
309 * Deletes the element named *@element_name inside *@structure.
313 * ASN1_SUCCESS: Everything OK.
315 * ASN1_ELEMENT_NOT_FOUND: The name element was not found.
319 asn1_delete_element(ASN1_TYPE structure
,const char *element_name
)
321 node_asn
*p2
,*p3
,*source_node
;
323 source_node
=_asn1_find_node(structure
,element_name
);
325 if(source_node
==ASN1_TYPE_EMPTY
) return ASN1_ELEMENT_NOT_FOUND
;
327 p2
=source_node
->right
;
328 p3
=_asn1_find_left(source_node
);
330 p3
=_asn1_find_up(source_node
);
332 _asn1_set_down(p3
,p2
);
334 if(source_node
->right
) source_node
->right
->left
=NULL
;
336 else _asn1_set_right(p3
,p2
);
338 return asn1_delete_structure(&source_node
);
343 _asn1_copy_structure3(node_asn
*source_node
)
345 node_asn
*dest_node
,*p_s
,*p_d
,*p_d_prev
;
346 int len
,len2
,move
, tlen
;
348 if(source_node
==NULL
) return NULL
;
350 dest_node
=_asn1_add_node_only(source_node
->type
);
359 if(p_s
->name
) _asn1_set_name(p_d
,p_s
->name
);
361 switch(type_field(p_s
->type
)){
362 case TYPE_OCTET_STRING
: case TYPE_BIT_STRING
: case TYPE_GENERALSTRING
:
365 len
=_asn1_get_length_der(p_s
->value
,&len2
);
366 _asn1_set_value(p_d
,p_s
->value
,len
+len2
);
369 tlen
= strlen(p_s
->value
);
372 _asn1_set_value(p_d
,p_s
->value
,tlen
+1);
383 p_d
=_asn1_add_node_only(p_s
->type
);
384 _asn1_set_down(p_d_prev
,p_d
);
389 if(p_s
==source_node
) break;
395 p_d
=_asn1_add_node_only(p_s
->type
);
396 _asn1_set_right(p_d_prev
,p_d
);
401 p_s
=_asn1_find_up(p_s
);
402 p_d
=_asn1_find_up(p_d
);
404 }while(p_s
!=source_node
);
411 _asn1_copy_structure2(node_asn
*root
,const char *source_name
)
413 node_asn
*source_node
;
415 source_node
=_asn1_find_node(root
,source_name
);
417 return _asn1_copy_structure3(source_node
);
423 _asn1_type_choice_config(node_asn
*node
)
425 node_asn
*p
,*p2
,*p3
,*p4
;
428 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
433 while(!((p
==node
) && (move
==UP
))){
435 if((type_field(p
->type
)==TYPE_CHOICE
) &&
436 (p
->type
&CONST_TAG
)){
439 if(type_field(p2
->type
)!=TYPE_TAG
){
441 p3
=_asn1_find_left(p2
);
443 if(type_field(p3
->type
)==TYPE_TAG
){
444 p4
=_asn1_add_node_only(p3
->type
);
445 tlen
= strlen(p3
->value
);
447 _asn1_set_value(p4
,p3
->value
,tlen
+1);
448 _asn1_set_right(p4
,p2
->down
);
449 _asn1_set_down(p2
,p4
);
451 p3
=_asn1_find_left(p3
);
456 p
->type
&=~(CONST_TAG
);
460 if(type_field(p2
->type
)==TYPE_TAG
) asn1_delete_structure(&p2
);
469 if(p
->down
) p
=p
->down
;
473 if(p
==node
) {move
=UP
; continue;}
476 if(p
->right
) p
=p
->right
;
479 if(move
==UP
) p
=_asn1_find_up(p
);
487 _asn1_expand_identifier(node_asn
**node
,node_asn
*root
)
490 char name2
[MAX_NAME_SIZE
+2];
493 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
498 while(!((p
==*node
) && (move
==UP
))){
500 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
501 _asn1_str_cpy(name2
, sizeof(name2
), root
->name
);
502 _asn1_str_cat(name2
, sizeof(name2
), ".");
503 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
504 p2
=_asn1_copy_structure2(root
,name2
);
506 return ASN1_IDENTIFIER_NOT_FOUND
;
508 _asn1_set_name(p2
,p
->name
);
511 if(p
->right
) p
->right
->left
=p2
;
514 while(p3
->right
) p3
=p3
->right
;
515 _asn1_set_right(p3
,p2
->down
);
516 _asn1_set_down(p2
,p
->down
);
519 p3
=_asn1_find_left(p
);
520 if(p3
) _asn1_set_right(p3
,p2
);
523 if(p3
) _asn1_set_down(p3
,p2
);
529 if(p
->type
& CONST_SIZE
) p2
->type
|=CONST_SIZE
;
530 if(p
->type
& CONST_TAG
) p2
->type
|=CONST_TAG
;
531 if(p
->type
& CONST_OPTION
) p2
->type
|=CONST_OPTION
;
532 if(p
->type
& CONST_DEFAULT
) p2
->type
|=CONST_DEFAULT
;
533 if(p
->type
& CONST_SET
) p2
->type
|=CONST_SET
;
534 if(p
->type
& CONST_NOT_USED
) p2
->type
|=CONST_NOT_USED
;
536 if(p
==*node
) *node
=p2
;
537 _asn1_remove_node(p
);
547 if(p
->down
) p
=p
->down
;
551 if(p
==*node
) {move
=UP
; continue;}
554 if(p
->right
) p
=p
->right
;
557 if(move
==UP
) p
=_asn1_find_up(p
);
565 * asn1_create_element - Creates a structure of type SOURCE_NAME.
566 * @definitions: pointer to the structure returned by "parser_asn1" function
567 * @source_name: the name of the type of the new structure (must be
568 * inside p_structure).
569 * @element: pointer to the structure created.
571 * Creates a structure of type @source_name. Example using
574 * rc = asn1_create_structure(cert_def, "PKIX1.Certificate",
579 * ASN1_SUCCESS: Creation OK.
581 * ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
584 asn1_create_element(ASN1_TYPE definitions
,const char *source_name
,
590 dest_node
=_asn1_copy_structure2(definitions
,source_name
);
592 if(dest_node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
594 _asn1_set_name(dest_node
,"");
596 res
=_asn1_expand_identifier(&dest_node
,definitions
);
597 _asn1_type_choice_config(dest_node
);
606 * asn1_print_structure - Prints on the standard output the structure's tree
607 * @out: pointer to the output file (e.g. stdout).
608 * @structure: pointer to the structure that you want to visit.
609 * @name: an element of the structure
610 * @mode: specify how much of the structure to print, can be
611 * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
612 * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
614 * Prints on the @out file descriptor the structure's tree starting
615 * from the @name element inside the structure @structure.
618 asn1_print_structure(FILE *out
,ASN1_TYPE structure
,const char *name
,int mode
)
621 int k
,indent
=0,len
,len2
,len3
;
623 if(out
==NULL
) return;
625 root
=_asn1_find_node(structure
,name
);
627 if(root
==NULL
) return;
631 if(mode
== ASN1_PRINT_ALL
){
632 for(k
=0;k
<indent
;k
++)fprintf(out
," ");
633 fprintf(out
,"name:");
634 if(p
->name
) fprintf(out
,"%s ",p
->name
);
635 else fprintf(out
,"NULL ");
638 switch(type_field(p
->type
)){
644 for(k
=0;k
<indent
;k
++)fprintf(out
," ");
645 fprintf(out
,"name:");
646 if(p
->name
) fprintf(out
,"%s ",p
->name
);
647 else fprintf(out
,"NULL ");
651 if(mode
!= ASN1_PRINT_NAME
){
652 switch(type_field(p
->type
)){
654 if(mode
== ASN1_PRINT_ALL
)
655 fprintf(out
,"type:CONST");break;
657 if(mode
== ASN1_PRINT_ALL
)
658 fprintf(out
,"type:TAG");break;
660 if(mode
== ASN1_PRINT_ALL
)
661 fprintf(out
,"type:SIZE");break;
663 fprintf(out
,"type:DEFAULT");break;
665 fprintf(out
,"type:NULL");break;
666 case TYPE_IDENTIFIER
:
667 fprintf(out
,"type:IDENTIFIER");break;
669 fprintf(out
,"type:INTEGER");break;
670 case TYPE_ENUMERATED
:
671 fprintf(out
,"type:ENUMERATED");break;
673 fprintf(out
,"type:TIME");break;
675 fprintf(out
,"type:BOOLEAN");break;
677 fprintf(out
,"type:SEQUENCE");break;
678 case TYPE_BIT_STRING
:
679 fprintf(out
,"type:BIT_STR");break;
680 case TYPE_OCTET_STRING
:
681 fprintf(out
,"type:OCT_STR");break;
682 case TYPE_GENERALSTRING
:
683 fprintf(out
,"type:GENERALSTRING");break;
684 case TYPE_SEQUENCE_OF
:
685 fprintf(out
,"type:SEQ_OF");break;
687 fprintf(out
,"type:OBJ_ID");break;
689 fprintf(out
,"type:ANY");break;
691 fprintf(out
,"type:SET");break;
693 fprintf(out
,"type:SET_OF");break;
695 fprintf(out
,"type:CHOICE");break;
696 case TYPE_DEFINITIONS
:
697 fprintf(out
,"type:DEFINITIONS");break;
703 if((mode
== ASN1_PRINT_NAME_TYPE_VALUE
) ||
704 (mode
== ASN1_PRINT_ALL
)){
705 switch(type_field(p
->type
)){
707 if(mode
== ASN1_PRINT_ALL
)
708 if(p
->value
) fprintf(out
," value:%s",p
->value
);
711 if(mode
== ASN1_PRINT_ALL
)
712 if (p
->value
) fprintf(out
," value:%s",p
->value
);
715 if(mode
== ASN1_PRINT_ALL
)
716 if(p
->value
) fprintf(out
," value:%s",p
->value
);
719 if(p
->value
) fprintf(out
," value:%s",p
->value
);
720 else if(p
->type
& CONST_TRUE
) fprintf(out
," value:TRUE");
721 else if(p
->type
& CONST_FALSE
) fprintf(out
," value:FALSE");
723 case TYPE_IDENTIFIER
:
724 if(p
->value
) fprintf(out
," value:%s",p
->value
);
729 len
=_asn1_get_length_der(p
->value
,&len2
);
730 fprintf(out
," value:0x");
731 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
734 case TYPE_ENUMERATED
:
737 len
=_asn1_get_length_der(p
->value
,&len2
);
738 fprintf(out
," value:0x");
739 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
743 if(p
->value
) fprintf(out
," value:%s",p
->value
);
747 if(p
->value
[0]=='T') fprintf(out
," value:TRUE");
748 else if(p
->value
[0]=='F') fprintf(out
," value:FALSE");
751 case TYPE_BIT_STRING
:
754 len
=_asn1_get_length_der(p
->value
,&len2
);
755 fprintf(out
," value(%i):",(len
-1)*8-(p
->value
[len2
]));
756 for(k
=1;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
759 case TYPE_OCTET_STRING
:
762 len
=_asn1_get_length_der(p
->value
,&len2
);
763 fprintf(out
," value:");
764 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
767 case TYPE_GENERALSTRING
:
770 len
=_asn1_get_length_der(p
->value
,&len2
);
771 fprintf(out
," value:");
772 for(k
=0;k
<len
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len2
]);
776 if(p
->value
) fprintf(out
," value:%s",p
->value
);
781 len2
=_asn1_get_length_der(p
->value
,&len3
);
782 fprintf(out
," value:");
783 for(k
=0;k
<len2
;k
++) fprintf(out
,"%02x",(p
->value
)[k
+len3
]);
789 case TYPE_DEFINITIONS
:
790 case TYPE_SEQUENCE_OF
:
799 if(mode
==ASN1_PRINT_ALL
){
800 if(p
->type
&0x1FFFFF00){
801 fprintf(out
," attr:");
802 if(p
->type
& CONST_UNIVERSAL
) fprintf(out
,"UNIVERSAL,");
803 if(p
->type
& CONST_PRIVATE
) fprintf(out
,"PRIVATE,");
804 if(p
->type
& CONST_APPLICATION
) fprintf(out
,"APPLICATION,");
805 if(p
->type
& CONST_EXPLICIT
) fprintf(out
,"EXPLICIT,");
806 if(p
->type
& CONST_IMPLICIT
) fprintf(out
,"IMPLICIT,");
807 if(p
->type
& CONST_TAG
) fprintf(out
,"TAG,");
808 if(p
->type
& CONST_DEFAULT
) fprintf(out
,"DEFAULT,");
809 if(p
->type
& CONST_TRUE
) fprintf(out
,"TRUE,");
810 if(p
->type
& CONST_FALSE
) fprintf(out
,"FALSE,");
811 if(p
->type
& CONST_LIST
) fprintf(out
,"LIST,");
812 if(p
->type
& CONST_MIN_MAX
) fprintf(out
,"MIN_MAX,");
813 if(p
->type
& CONST_OPTION
) fprintf(out
,"OPTION,");
814 if(p
->type
& CONST_1_PARAM
) fprintf(out
,"1_PARAM,");
815 if(p
->type
& CONST_SIZE
) fprintf(out
,"SIZE,");
816 if(p
->type
& CONST_DEFINED_BY
) fprintf(out
,"DEF_BY,");
817 if(p
->type
& CONST_GENERALIZED
) fprintf(out
,"GENERALIZED,");
818 if(p
->type
& CONST_UTC
) fprintf(out
,"UTC,");
819 if(p
->type
& CONST_SET
) fprintf(out
,"SET,");
820 if(p
->type
& CONST_NOT_USED
) fprintf(out
,"NOT_USED,");
821 if(p
->type
& CONST_ASSIGN
) fprintf(out
,"ASSIGNMENT,");
825 if(mode
== ASN1_PRINT_ALL
){
829 switch(type_field(p
->type
)){
847 else if(p
->right
) p
=p
->right
;
868 * asn1_number_of_elements - Counts the number of elements of a structure.
869 * @element: pointer to the root of an ASN1 structure.
870 * @name: the name of a sub-structure of ROOT.
871 * @num: pointer to an integer where the result will be stored
873 * Counts the number of elements of a sub-structure called NAME with
874 * names equal to "?1","?2", ...
878 * ASN1_SUCCESS: Creation OK.
880 * ASN1_ELEMENT_NOT_FOUND: NAME isn't known.
882 * ASN1_GENERIC_ERROR: Pointer num equal to NULL.
886 asn1_number_of_elements(ASN1_TYPE element
,const char *name
,int *num
)
890 if(num
==NULL
) return ASN1_GENERIC_ERROR
;
894 node
=_asn1_find_node(element
,name
);
895 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
900 if((p
->name
) && (p
->name
[0]=='?')) (*num
)++;
909 * asn1_find_structure_from_oid - Locate structure defined by a specific OID.
910 * @definitions: ASN1 definitions
911 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
913 * Search the structure that is defined just after an OID definition.
915 * Returns: NULL when OIDVALUE not found, otherwise the pointer to a
916 * constant string that contains the element name defined just
921 asn1_find_structure_from_oid (ASN1_TYPE definitions
,
922 const char *oidValue
)
924 char definitionsName
[MAX_NAME_SIZE
],name
[2*MAX_NAME_SIZE
+1];
925 char value
[MAX_NAME_SIZE
];
930 if((definitions
==ASN1_TYPE_EMPTY
) || (oidValue
==NULL
))
931 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
934 strcpy(definitionsName
,definitions
->name
);
935 strcat(definitionsName
,".");
937 /* search the OBJECT_ID into definitions */
940 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
941 (p
->type
& CONST_ASSIGN
)){
942 strcpy(name
,definitionsName
);
943 strcat(name
,p
->name
);
946 result
=asn1_read_value(definitions
,name
,value
,&len
);
948 if((result
== ASN1_SUCCESS
) && (!strcmp(oidValue
,value
))){
950 if(p
==NULL
) /* reach the end of ASN1 definitions */
951 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */
959 return NULL
; /* ASN1_ELEMENT_NOT_FOUND; */