2 * Copyright (C) 2000,2001 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
24 #include "parser_aux.h"
27 #include "structure.h"
30 char _asn1_identifierMissing
[MAX_NAME_SIZE
+1]; /* identifier name not found */
32 /***********************************************/
34 /* Description: type used in the list during */
35 /* the structure creation. */
36 /***********************************************/
37 typedef struct list_struct
{
39 struct list_struct
*next
;
43 /* Pointer to the first element of the list */
44 list_type
*firstElement
=NULL
;
46 /******************************************************/
47 /* Function : _asn1_add_node */
48 /* Description: creates a new NODE_ASN element and */
49 /* puts it in the list pointed by firstElement. */
51 /* type: type of the new element (see TYPE_ */
52 /* and CONST_ constants). */
53 /* Return: pointer to the new element. */
54 /******************************************************/
56 _asn1_add_node(unsigned int type
)
58 list_type
*listElement
;
61 punt
=(node_asn
*) _asn1_malloc(sizeof(node_asn
));
62 if (punt
==NULL
) return NULL
;
64 listElement
=(list_type
*) _asn1_malloc(sizeof(list_type
));
65 if(listElement
==NULL
){
70 listElement
->node
=punt
;
71 listElement
->next
=firstElement
;
72 firstElement
=listElement
;
84 /******************************************************************/
85 /* Function : _asn1_find_mode */
86 /* Description: searches an element called NAME starting from */
87 /* POINTER. The name is composed by differents */
88 /* identifiers separated by dots.When *POINTER has a */
89 /* name, the first identifier must be the name of */
90 /* *POINTER, otherwise it must be the name of one */
91 /* child of *POINTER. */
93 /* pointer: NODE_ASN element pointer. */
94 /* name: null terminated string with the element's name to find.*/
95 /* Return: the searching result. NULL if not found. */
96 /******************************************************************/
98 _asn1_find_node(node_asn
*pointer
,const char *name
)
101 char *n_end
,n
[MAX_NAME_SIZE
+1];
104 if(pointer
== NULL
) return NULL
;
106 if(name
==NULL
) return NULL
;
111 if(p
->name
!= NULL
){ /* has *pointer got a name ? */
112 n_end
=strchr(n_start
,'.'); /* search the first dot */
114 memcpy(n
,n_start
,n_end
-n_start
);
120 _asn1_str_cpy(n
,sizeof(n
),n_start
);
125 if((p
->name
) && (!strcmp(p
->name
,n
))) break;
129 if(p
==NULL
) return NULL
;
131 else{ /* *pointer doesn't have a name */
136 while(n_start
){ /* Has the end of NAME been reached? */
137 n_end
=strchr(n_start
,'.'); /* search the next dot */
139 memcpy(n
,n_start
,n_end
-n_start
);
145 _asn1_str_cpy(n
,sizeof(n
),n_start
);
149 if(p
->down
==NULL
) return NULL
;
153 /* The identifier "?LAST" indicates the last element
154 in the right chain. */
155 if(!strcmp(n
,"?LAST")){
156 if(p
==NULL
) return NULL
;
157 while(p
->right
) p
=p
->right
;
159 else{ /* no "?LAST" */
161 if((p
->name
) && (!strcmp(p
->name
,n
))) break;
164 if(p
==NULL
) return NULL
;
172 /******************************************************************/
173 /* Function : _asn1_set_value */
174 /* Description: sets the field VALUE in a NODE_ASN element. The */
175 /* previous value (if exist) will be lost */
177 /* node: element pointer. */
178 /* value: pointer to the value that you want to set. */
179 /* len: character number of value. */
180 /* Return: pointer to the NODE_ASN element. */
181 /******************************************************************/
183 _asn1_set_value(node_asn
*node
,const unsigned char *value
,unsigned int len
)
186 if(node
==NULL
) return node
;
188 _asn1_free(node
->value
);
191 if(!len
) return node
;
192 node
->value
=(unsigned char *) _asn1_malloc(len
);
193 if (node
->value
==NULL
) return NULL
;
195 memcpy(node
->value
,value
,len
);
199 /******************************************************************/
200 /* Function : _asn1_set_name */
201 /* Description: sets the field NAME in a NODE_ASN element. The */
202 /* previous value (if exist) will be lost */
204 /* node: element pointer. */
205 /* name: a null terminated string with the name that you want */
207 /* Return: pointer to the NODE_ASN element. */
208 /******************************************************************/
210 _asn1_set_name(node_asn
*node
,const char *name
)
212 if(node
==NULL
) return node
;
215 _asn1_free(node
->name
);
219 if(name
==NULL
) return node
;
223 node
->name
=(char *) _asn1_strdup( name
);
224 if (node
->name
==NULL
) return NULL
;
226 else node
->name
=NULL
;
230 /******************************************************************/
231 /* Function : _asn1_set_right */
232 /* Description: sets the field RIGHT in a NODE_ASN element. */
234 /* node: element pointer. */
235 /* right: pointer to a NODE_ASN element that you want be pointed*/
237 /* Return: pointer to *NODE. */
238 /******************************************************************/
240 _asn1_set_right(node_asn
*node
,node_asn
*right
)
242 if(node
==NULL
) return node
;
244 if(right
) right
->left
=node
;
248 /******************************************************************/
249 /* Function : _asn1_get_right */
250 /* Description: returns the element pointed by the RIGHT field of */
251 /* a NODE_ASN element. */
253 /* node: NODE_ASN element pointer. */
254 /* Return: field RIGHT of NODE. */
255 /******************************************************************/
257 _asn1_get_right(node_asn
*node
)
259 if(node
==NULL
) return NULL
;
263 /******************************************************************/
264 /* Function : _asn1_get_last_right */
265 /* Description: return the last element along the right chain. */
267 /* node: starting element pointer. */
268 /* Return: pointer to the last element along the right chain. */
269 /******************************************************************/
271 _asn1_get_last_right(node_asn
*node
)
275 if(node
==NULL
) return NULL
;
277 while(p
->right
) p
=p
->right
;
281 /******************************************************************/
282 /* Function : _asn1_set_down */
283 /* Description: sets the field DOWN in a NODE_ASN element. */
285 /* node: element pointer. */
286 /* down: pointer to a NODE_ASN element that you want be pointed */
288 /* Return: pointer to *NODE. */
289 /******************************************************************/
291 _asn1_set_down(node_asn
*node
,node_asn
*down
)
293 if(node
==NULL
) return node
;
295 if(down
) down
->left
=node
;
299 /******************************************************************/
300 /* Function : _asn1_get_down */
301 /* Description: returns the element pointed by the DOWN field of */
302 /* a NODE_ASN element. */
304 /* node: NODE_ASN element pointer. */
305 /* Return: field DOWN of NODE. */
306 /******************************************************************/
308 _asn1_get_down(node_asn
*node
)
310 if(node
==NULL
) return NULL
;
314 /******************************************************************/
315 /* Function : _asn1_get_name */
316 /* Description: returns the name of a NODE_ASN element. */
318 /* node: NODE_ASN element pointer. */
319 /* Return: a null terminated string. */
320 /******************************************************************/
322 _asn1_get_name(node_asn
*node
)
324 if(node
==NULL
) return NULL
;
328 /******************************************************************/
329 /* Function : _asn1_mod_type */
330 /* Description: change the field TYPE of an NODE_ASN element. */
331 /* The new value is the old one | (bitwise or) the */
332 /* paramener VALUE. */
334 /* node: NODE_ASN element pointer. */
335 /* value: the integer value that must be or-ed with the current */
336 /* value of field TYPE. */
337 /* Return: NODE pointer. */
338 /******************************************************************/
340 _asn1_mod_type(node_asn
*node
,unsigned int value
)
342 if(node
==NULL
) return node
;
348 /******************************************************************/
349 /* Function : _asn1_remove_node */
350 /* Description: gets free the memory allocated for an NODE_ASN */
351 /* element (not the elements pointed by it). */
353 /* node: NODE_ASN element pointer. */
354 /******************************************************************/
356 _asn1_remove_node(node_asn
*node
)
358 if(node
==NULL
) return;
360 if (node
->name
!=NULL
)
361 _asn1_free(node
->name
);
362 if (node
->value
!=NULL
)
363 _asn1_free(node
->value
);
367 /******************************************************************/
368 /* Function : _asn1_find_up */
369 /* Description: return the father of the NODE_ASN element. */
371 /* node: NODE_ASN element pointer. */
372 /* Return: Null if not found. */
373 /******************************************************************/
375 _asn1_find_up(node_asn
*node
)
379 if(node
==NULL
) return NULL
;
383 while((p
->left
!=NULL
) && (p
->left
->right
==p
)) p
=p
->left
;
388 /******************************************************************/
389 /* Function : _asn1_delete_list */
390 /* Description: deletes the list elements (not the elements */
391 /* pointed by them). */
392 /******************************************************************/
394 _asn1_delete_list(void)
396 list_type
*listElement
;
399 listElement
=firstElement
;
400 firstElement
=firstElement
->next
;
401 _asn1_free(listElement
);
405 /******************************************************************/
406 /* Function : _asn1_delete_list_and nodes */
407 /* Description: deletes the list elements and the elements */
408 /* pointed by them. */
409 /******************************************************************/
411 _asn1_delete_list_and_nodes(void)
413 list_type
*listElement
;
416 listElement
=firstElement
;
417 firstElement
=firstElement
->next
;
418 _asn1_remove_node(listElement
->node
);
419 _asn1_free(listElement
);
425 _asn1_ltostr(long v
,char *str
)
442 temp
[start
+count
]='0'+(char)r
;
447 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
453 /******************************************************************/
454 /* Function : _asn1_change_integer_value */
455 /* Description: converts into DER coding the value assign to an */
456 /* INTEGER constant. */
458 /* node: root of an ASN1element. */
460 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
461 /* otherwise ASN1_SUCCESS */
462 /******************************************************************/
464 _asn1_change_integer_value(ASN1_TYPE node
)
467 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
468 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+1];
471 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
475 if((type_field(p
->type
)==TYPE_INTEGER
) && (p
->type
&CONST_ASSIGN
)){
477 _asn1_convert_integer(p
->value
,val
,sizeof(val
), &len
);
478 _asn1_octet_der(val
,len
,val2
,&len
);
479 _asn1_set_value(p
,val2
,len
);
488 else if(p
->right
) p
=p
->right
;
509 /******************************************************************/
510 /* Function : _asn1_expand_object_id */
511 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
513 /* node: root of an ASN1 element. */
515 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
516 /* otherwise ASN1_SUCCESS */
517 /******************************************************************/
519 _asn1_expand_object_id(ASN1_TYPE node
)
521 node_asn
*p
,*p2
,*p3
,*p4
,*p5
;
522 char name_root
[MAX_NAME_SIZE
],name2
[2*MAX_NAME_SIZE
+1];
525 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
527 _asn1_str_cpy(name_root
, sizeof(name_root
), node
->name
);
532 while(!((p
==node
) && (move
==UP
))){
534 if((type_field(p
->type
)==TYPE_OBJECT_ID
) && (p
->type
&CONST_ASSIGN
)){
536 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
537 if(p2
->value
&& !isdigit(p2
->value
[0])){
538 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
539 _asn1_str_cat(name2
, sizeof(name2
), ".");
540 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
541 p3
=_asn1_find_node(node
,name2
);
542 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
543 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
544 _asn1_set_down(p
,p2
->right
);
545 _asn1_remove_node(p2
);
549 if(type_field(p4
->type
)==TYPE_CONSTANT
){
550 p5
=_asn1_add_node_only(TYPE_CONSTANT
);
551 _asn1_set_name(p5
,p4
->name
);
552 tlen
= strlen( p4
->value
);
554 _asn1_set_value(p5
,p4
->value
,tlen
+1);
556 _asn1_set_right(p5
,p
->down
);
557 _asn1_set_down(p
,p5
);
560 _asn1_set_right(p5
,p2
->right
);
561 _asn1_set_right(p2
,p5
);
577 if(p
->down
) p
=p
->down
;
581 if(p
==node
) {move
=UP
; continue;}
584 if(p
->right
) p
=p
->right
;
587 if(move
==UP
) p
=_asn1_find_up(p
);
591 /*******************************/
593 /*******************************/
597 while(!((p
==node
) && (move
==UP
))){
599 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
600 (p
->type
&CONST_DEFAULT
)){
602 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
603 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
604 _asn1_str_cat(name2
, sizeof(name2
), ".");
605 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
606 p3
=_asn1_find_node(node
,name2
);
607 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
608 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
612 if(type_field(p4
->type
)==TYPE_CONSTANT
){
613 if(name2
[0]) _asn1_str_cat(name2
,sizeof(name2
),".");
614 _asn1_str_cat(name2
,sizeof(name2
),p4
->value
);
618 tlen
= strlen(name2
);
620 _asn1_set_value(p2
,name2
,tlen
+1);
628 if(p
->down
) p
=p
->down
;
632 if(p
==node
) {move
=UP
; continue;}
635 if(p
->right
) p
=p
->right
;
638 if(move
==UP
) p
=_asn1_find_up(p
);
645 /******************************************************************/
646 /* Function : _asn1_type_set_config */
647 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
648 /* in the fields of the SET elements. */
650 /* node: root of an ASN1 element. */
652 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
653 /* otherwise ASN1_SUCCESS */
654 /******************************************************************/
656 _asn1_type_set_config(ASN1_TYPE node
)
661 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
666 while(!((p
==node
) && (move
==UP
))){
668 if(type_field(p
->type
)==TYPE_SET
){
671 if(type_field(p2
->type
)!=TYPE_TAG
)
672 p2
->type
|=CONST_SET
|CONST_NOT_USED
;
681 if(p
->down
) p
=p
->down
;
685 if(p
==node
) {move
=UP
; continue;}
688 if(p
->right
) p
=p
->right
;
691 if(move
==UP
) p
=_asn1_find_up(p
);
698 /******************************************************************/
699 /* Function : _asn1_check_identifier */
700 /* Description: checks the definitions of all the identifiers */
701 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
702 /* The _asn1_identifierMissing global variable is filled if */
705 /* node: root of an ASN1 element. */
707 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
708 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
709 /* otherwise ASN1_SUCCESS */
710 /******************************************************************/
712 _asn1_check_identifier(ASN1_TYPE node
)
715 char name2
[MAX_NAME_SIZE
*2+2];
717 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
721 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
722 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
723 _asn1_str_cat(name2
, sizeof(name2
), ".");
724 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
725 p2
=_asn1_find_node(node
,name2
);
727 strcpy(_asn1_identifierMissing
,p
->value
);
728 return ASN1_IDENTIFIER_NOT_FOUND
;
731 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
732 (p
->type
&CONST_DEFAULT
)){
734 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
735 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
736 _asn1_str_cat(name2
, sizeof(name2
), ".");
737 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
738 strcpy(_asn1_identifierMissing
,p2
->value
);
739 p2
=_asn1_find_node(node
,name2
);
740 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
741 !(p2
->type
&CONST_ASSIGN
))
742 return ASN1_IDENTIFIER_NOT_FOUND
;
744 _asn1_identifierMissing
[0]=0;
747 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
748 (p
->type
&CONST_ASSIGN
)){
750 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
751 if(p2
->value
&& !isdigit(p2
->value
[0])){
752 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
753 _asn1_str_cat(name2
, sizeof(name2
), ".");
754 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
755 strcpy(_asn1_identifierMissing
,p2
->value
);
756 p2
=_asn1_find_node(node
,name2
);
757 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
758 !(p2
->type
&CONST_ASSIGN
))
759 return ASN1_IDENTIFIER_NOT_FOUND
;
761 _asn1_identifierMissing
[0]=0;
769 else if(p
->right
) p
=p
->right
;
789 /******************************************************************/
790 /* Function : _asn1_set_default_tag */
791 /* Description: sets the default IMPLICIT or EXPLICIT property in */
792 /* the tagged elements that don't have this declaration. */
794 /* node: pointer to a DEFINITIONS element. */
796 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
797 /* a DEFINITIONS element, */
798 /* otherwise ASN1_SUCCESS */
799 /******************************************************************/
801 _asn1_set_default_tag(ASN1_TYPE node
)
805 if((node
==NULL
) || (type_field(node
->type
)!=TYPE_DEFINITIONS
))
806 return ASN1_ELEMENT_NOT_FOUND
;
810 if((type_field(p
->type
)==TYPE_TAG
) &&
811 !(p
->type
&CONST_EXPLICIT
) &&
812 !(p
->type
&CONST_IMPLICIT
)){
813 if(node
->type
&CONST_EXPLICIT
) p
->type
|=CONST_EXPLICIT
;
814 else p
->type
|=CONST_IMPLICIT
;
820 else if(p
->right
) p
=p
->right
;
842 parse_version_number( const char *s
, int *number
)
846 if( *s
== '0' && isdigit(s
[1]) )
847 return NULL
; /* leading zeros are not allowed */
848 for ( ; isdigit(*s
); s
++ ) {
853 return val
< 0? NULL
: s
;
856 /* The parse version functions were copied from libgcrypt.
859 parse_version_string( const char *s
, int *major
, int *minor
, int *micro
)
861 s
= parse_version_number( s
, major
);
862 if( !s
|| *s
!= '.' )
865 s
= parse_version_number( s
, minor
);
866 if( !s
|| *s
!= '.' )
869 s
= parse_version_number( s
, micro
);
872 return s
; /* patchlevel */
876 * asn1_check_version - check for library version
877 * @req_version: Required version number, or NULL.
879 * Check that the the version of the library is at minimum the
880 * requested one and return the version string; return %NULL if the
881 * condition is not satisfied. If a %NULL is passed to this function,
882 * no check is done, but the version string is simply returned.
884 * See %LIBTASN1_VERSION for a suitable @req_version string.
886 * Return value: Version string of run-time library, or %NULL if the
887 * run-time library does not meet the required version number.
890 asn1_check_version( const char *req_version
)
892 const char *ver
= LIBTASN1_VERSION
;
893 int my_major
, my_minor
, my_micro
;
894 int rq_major
, rq_minor
, rq_micro
;
895 const char *my_plvl
, *rq_plvl
;
900 my_plvl
= parse_version_string( ver
, &my_major
, &my_minor
, &my_micro
);
902 return NULL
; /* very strange our own version is bogus */
903 rq_plvl
= parse_version_string( req_version
, &rq_major
, &rq_minor
,
906 return NULL
; /* req version string is invalid */
908 if ( my_major
> rq_major
909 || (my_major
== rq_major
&& my_minor
> rq_minor
)
910 || (my_major
== rq_major
&& my_minor
== rq_minor
911 && my_micro
> rq_micro
)
912 || (my_major
== rq_major
&& my_minor
== rq_minor
913 && my_micro
== rq_micro
914 && strcmp( my_plvl
, rq_plvl
) >= 0) ) {