2 * Copyright (C) 2004, 2006 Free Software Foundation
3 * Copyright (C) 2000,2001 Fabio Fiorina
5 * This file is part of LIBTASN1.
7 * The LIBTASN1 library is free software; you can redistribute it
8 * and/or 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, but
13 * 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
25 #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
;
86 * @pointer: NODE_ASN element pointer.
87 * @name: null terminated string with the element's name to find.
89 * Searches for an element called NAME starting from POINTER. The
90 * name is composed by differents identifiers separated by dots. When
91 * *POINTER has a name, the first identifier must be the name of
92 * *POINTER, otherwise it must be the name of one child of *POINTER.
94 * Return value: the searching result. NULL if not found.
97 asn1_find_node(ASN1_TYPE pointer
, const char *name
)
100 char *n_end
,n
[MAX_NAME_SIZE
+1];
103 if(pointer
== NULL
) return NULL
;
105 if(name
==NULL
) return NULL
;
110 if(p
->name
!= NULL
){ /* has *pointer got a name ? */
111 n_end
=strchr(n_start
,'.'); /* search the first dot */
113 memcpy(n
,n_start
,n_end
-n_start
);
119 _asn1_str_cpy(n
,sizeof(n
),n_start
);
124 if((p
->name
) && (!strcmp(p
->name
,n
))) break;
128 if(p
==NULL
) return NULL
;
130 else{ /* *pointer doesn't have a name */
135 while(n_start
){ /* Has the end of NAME been reached? */
136 n_end
=strchr(n_start
,'.'); /* search the next dot */
138 memcpy(n
,n_start
,n_end
-n_start
);
144 _asn1_str_cpy(n
,sizeof(n
),n_start
);
148 if(p
->down
==NULL
) return NULL
;
152 /* The identifier "?LAST" indicates the last element
153 in the right chain. */
154 if(!strcmp(n
,"?LAST")){
155 if(p
==NULL
) return NULL
;
156 while(p
->right
) p
=p
->right
;
158 else{ /* no "?LAST" */
160 if((p
->name
) && (!strcmp(p
->name
,n
))) break;
163 if(p
==NULL
) return NULL
;
171 /******************************************************************/
172 /* Function : _asn1_set_value */
173 /* Description: sets the field VALUE in a NODE_ASN element. The */
174 /* previous value (if exist) will be lost */
176 /* node: element pointer. */
177 /* value: pointer to the value that you want to set. */
178 /* len: character number of value. */
179 /* Return: pointer to the NODE_ASN element. */
180 /******************************************************************/
182 _asn1_set_value(node_asn
*node
,const unsigned char *value
,unsigned int len
)
185 if(node
==NULL
) return node
;
187 _asn1_free(node
->value
);
191 if(!len
) return node
;
192 node
->value
=(unsigned char *) _asn1_malloc(len
);
193 if (node
->value
==NULL
) return NULL
;
194 node
->value_len
= len
;
196 memcpy(node
->value
,value
,len
);
200 /******************************************************************/
201 /* Function : _asn1_set_name */
202 /* Description: sets the field NAME in a NODE_ASN element. The */
203 /* previous value (if exist) will be lost */
205 /* node: element pointer. */
206 /* name: a null terminated string with the name that you want */
208 /* Return: pointer to the NODE_ASN element. */
209 /******************************************************************/
211 _asn1_set_name(node_asn
*node
,const char *name
)
213 if(node
==NULL
) return node
;
216 _asn1_free(node
->name
);
220 if(name
==NULL
) return node
;
224 node
->name
=(char *) _asn1_strdup( name
);
225 if (node
->name
==NULL
) return NULL
;
227 else node
->name
=NULL
;
231 /******************************************************************/
232 /* Function : _asn1_set_right */
233 /* Description: sets the field RIGHT in a NODE_ASN element. */
235 /* node: element pointer. */
236 /* right: pointer to a NODE_ASN element that you want be pointed*/
238 /* Return: pointer to *NODE. */
239 /******************************************************************/
241 _asn1_set_right(node_asn
*node
,node_asn
*right
)
243 if(node
==NULL
) return node
;
245 if(right
) right
->left
=node
;
249 /******************************************************************/
250 /* Function : _asn1_get_right */
251 /* Description: returns the element pointed by the RIGHT field of */
252 /* a NODE_ASN element. */
254 /* node: NODE_ASN element pointer. */
255 /* Return: field RIGHT of NODE. */
256 /******************************************************************/
258 _asn1_get_right(node_asn
*node
)
260 if(node
==NULL
) return NULL
;
264 /******************************************************************/
265 /* Function : _asn1_get_last_right */
266 /* Description: return the last element along the right chain. */
268 /* node: starting element pointer. */
269 /* Return: pointer to the last element along the right chain. */
270 /******************************************************************/
272 _asn1_get_last_right(node_asn
*node
)
276 if(node
==NULL
) return NULL
;
278 while(p
->right
) p
=p
->right
;
282 /******************************************************************/
283 /* Function : _asn1_set_down */
284 /* Description: sets the field DOWN in a NODE_ASN element. */
286 /* node: element pointer. */
287 /* down: pointer to a NODE_ASN element that you want be pointed */
289 /* Return: pointer to *NODE. */
290 /******************************************************************/
292 _asn1_set_down(node_asn
*node
,node_asn
*down
)
294 if(node
==NULL
) return node
;
296 if(down
) down
->left
=node
;
300 /******************************************************************/
301 /* Function : _asn1_get_down */
302 /* Description: returns the element pointed by the DOWN field of */
303 /* a NODE_ASN element. */
305 /* node: NODE_ASN element pointer. */
306 /* Return: field DOWN of NODE. */
307 /******************************************************************/
309 _asn1_get_down(node_asn
*node
)
311 if(node
==NULL
) return NULL
;
315 /******************************************************************/
316 /* Function : _asn1_get_name */
317 /* Description: returns the name of a NODE_ASN element. */
319 /* node: NODE_ASN element pointer. */
320 /* Return: a null terminated string. */
321 /******************************************************************/
323 _asn1_get_name(node_asn
*node
)
325 if(node
==NULL
) return NULL
;
329 /******************************************************************/
330 /* Function : _asn1_mod_type */
331 /* Description: change the field TYPE of an NODE_ASN element. */
332 /* The new value is the old one | (bitwise or) the */
333 /* paramener VALUE. */
335 /* node: NODE_ASN element pointer. */
336 /* value: the integer value that must be or-ed with the current */
337 /* value of field TYPE. */
338 /* Return: NODE pointer. */
339 /******************************************************************/
341 _asn1_mod_type(node_asn
*node
,unsigned int value
)
343 if(node
==NULL
) return node
;
349 /******************************************************************/
350 /* Function : _asn1_remove_node */
351 /* Description: gets free the memory allocated for an NODE_ASN */
352 /* element (not the elements pointed by it). */
354 /* node: NODE_ASN element pointer. */
355 /******************************************************************/
357 _asn1_remove_node(node_asn
*node
)
359 if(node
==NULL
) return;
361 if (node
->name
!=NULL
)
362 _asn1_free(node
->name
);
363 if (node
->value
!=NULL
)
364 _asn1_free(node
->value
);
370 * @node: NODE_ASN element pointer.
372 * Return the father of the NODE_ASN element.
374 * Return value: Return the father of the node, or %NULL if not found.
377 asn1_find_up(ASN1_TYPE node
)
381 if(node
==NULL
) return NULL
;
385 while((p
->left
!=NULL
) && (p
->left
->right
==p
)) p
=p
->left
;
390 /******************************************************************/
391 /* Function : _asn1_delete_list */
392 /* Description: deletes the list elements (not the elements */
393 /* pointed by them). */
394 /******************************************************************/
396 _asn1_delete_list(void)
398 list_type
*listElement
;
401 listElement
=firstElement
;
402 firstElement
=firstElement
->next
;
403 _asn1_free(listElement
);
407 /******************************************************************/
408 /* Function : _asn1_delete_list_and nodes */
409 /* Description: deletes the list elements and the elements */
410 /* pointed by them. */
411 /******************************************************************/
413 _asn1_delete_list_and_nodes(void)
415 list_type
*listElement
;
418 listElement
=firstElement
;
419 firstElement
=firstElement
->next
;
420 _asn1_remove_node(listElement
->node
);
421 _asn1_free(listElement
);
427 _asn1_ltostr(long v
,char *str
)
444 temp
[start
+count
]='0'+(char)r
;
449 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
455 /******************************************************************/
456 /* Function : _asn1_change_integer_value */
457 /* Description: converts into DER coding the value assign to an */
458 /* INTEGER constant. */
460 /* node: root of an ASN1element. */
462 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
463 /* otherwise ASN1_SUCCESS */
464 /******************************************************************/
466 _asn1_change_integer_value(ASN1_TYPE node
)
469 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
470 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+1];
473 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
477 if((type_field(p
->type
)==TYPE_INTEGER
) && (p
->type
&CONST_ASSIGN
)){
479 _asn1_convert_integer(p
->value
,val
,sizeof(val
), &len
);
480 asn1_octet_der(val
,len
,val2
,&len
);
481 _asn1_set_value(p
,val2
,len
);
490 else if(p
->right
) p
=p
->right
;
511 /******************************************************************/
512 /* Function : _asn1_expand_object_id */
513 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
515 /* node: root of an ASN1 element. */
517 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
518 /* otherwise ASN1_SUCCESS */
519 /******************************************************************/
521 _asn1_expand_object_id(ASN1_TYPE node
)
523 node_asn
*p
,*p2
,*p3
,*p4
,*p5
;
524 char name_root
[MAX_NAME_SIZE
],name2
[2*MAX_NAME_SIZE
+1];
527 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
529 _asn1_str_cpy(name_root
, sizeof(name_root
), node
->name
);
534 while(!((p
==node
) && (move
==UP
))){
536 if((type_field(p
->type
)==TYPE_OBJECT_ID
) && (p
->type
&CONST_ASSIGN
)){
538 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
539 if(p2
->value
&& !isdigit(p2
->value
[0])){
540 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
541 _asn1_str_cat(name2
, sizeof(name2
), ".");
542 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
543 p3
=asn1_find_node(node
,name2
);
544 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
545 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
546 _asn1_set_down(p
,p2
->right
);
547 _asn1_remove_node(p2
);
551 if(type_field(p4
->type
)==TYPE_CONSTANT
){
552 p5
=_asn1_add_node_only(TYPE_CONSTANT
);
553 _asn1_set_name(p5
,p4
->name
);
554 tlen
= strlen( p4
->value
);
556 _asn1_set_value(p5
,p4
->value
,tlen
+1);
558 _asn1_set_right(p5
,p
->down
);
559 _asn1_set_down(p
,p5
);
562 _asn1_set_right(p5
,p2
->right
);
563 _asn1_set_right(p2
,p5
);
579 if(p
->down
) p
=p
->down
;
583 if(p
==node
) {move
=UP
; continue;}
586 if(p
->right
) p
=p
->right
;
589 if(move
==UP
) p
=asn1_find_up(p
);
593 /*******************************/
595 /*******************************/
599 while(!((p
==node
) && (move
==UP
))){
601 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
602 (p
->type
&CONST_DEFAULT
)){
604 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
605 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
606 _asn1_str_cat(name2
, sizeof(name2
), ".");
607 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
608 p3
=asn1_find_node(node
,name2
);
609 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
610 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
614 if(type_field(p4
->type
)==TYPE_CONSTANT
){
615 if(name2
[0]) _asn1_str_cat(name2
,sizeof(name2
),".");
616 _asn1_str_cat(name2
,sizeof(name2
),p4
->value
);
620 tlen
= strlen(name2
);
622 _asn1_set_value(p2
,name2
,tlen
+1);
630 if(p
->down
) p
=p
->down
;
634 if(p
==node
) {move
=UP
; continue;}
637 if(p
->right
) p
=p
->right
;
640 if(move
==UP
) p
=asn1_find_up(p
);
647 /******************************************************************/
648 /* Function : _asn1_type_set_config */
649 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
650 /* in the fields of the SET elements. */
652 /* node: root of an ASN1 element. */
654 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
655 /* otherwise ASN1_SUCCESS */
656 /******************************************************************/
658 _asn1_type_set_config(ASN1_TYPE node
)
663 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
668 while(!((p
==node
) && (move
==UP
))){
670 if(type_field(p
->type
)==TYPE_SET
){
673 if(type_field(p2
->type
)!=TYPE_TAG
)
674 p2
->type
|=CONST_SET
|CONST_NOT_USED
;
683 if(p
->down
) p
=p
->down
;
687 if(p
==node
) {move
=UP
; continue;}
690 if(p
->right
) p
=p
->right
;
693 if(move
==UP
) p
=asn1_find_up(p
);
700 /******************************************************************/
701 /* Function : _asn1_check_identifier */
702 /* Description: checks the definitions of all the identifiers */
703 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
704 /* The _asn1_identifierMissing global variable is filled if */
707 /* node: root of an ASN1 element. */
709 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
710 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
711 /* otherwise ASN1_SUCCESS */
712 /******************************************************************/
714 _asn1_check_identifier(ASN1_TYPE node
)
717 char name2
[MAX_NAME_SIZE
*2+2];
719 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
723 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
724 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
725 _asn1_str_cat(name2
, sizeof(name2
), ".");
726 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
727 p2
=asn1_find_node(node
,name2
);
729 strcpy(_asn1_identifierMissing
,p
->value
);
730 return ASN1_IDENTIFIER_NOT_FOUND
;
733 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
734 (p
->type
&CONST_DEFAULT
)){
736 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
737 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
738 _asn1_str_cat(name2
, sizeof(name2
), ".");
739 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
740 strcpy(_asn1_identifierMissing
,p2
->value
);
741 p2
=asn1_find_node(node
,name2
);
742 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
743 !(p2
->type
&CONST_ASSIGN
))
744 return ASN1_IDENTIFIER_NOT_FOUND
;
746 _asn1_identifierMissing
[0]=0;
749 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
750 (p
->type
&CONST_ASSIGN
)){
752 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
753 if(p2
->value
&& !isdigit(p2
->value
[0])){
754 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
755 _asn1_str_cat(name2
, sizeof(name2
), ".");
756 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
757 strcpy(_asn1_identifierMissing
,p2
->value
);
758 p2
=asn1_find_node(node
,name2
);
759 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
760 !(p2
->type
&CONST_ASSIGN
))
761 return ASN1_IDENTIFIER_NOT_FOUND
;
763 _asn1_identifierMissing
[0]=0;
771 else if(p
->right
) p
=p
->right
;
791 /******************************************************************/
792 /* Function : _asn1_set_default_tag */
793 /* Description: sets the default IMPLICIT or EXPLICIT property in */
794 /* the tagged elements that don't have this declaration. */
796 /* node: pointer to a DEFINITIONS element. */
798 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
799 /* a DEFINITIONS element, */
800 /* otherwise ASN1_SUCCESS */
801 /******************************************************************/
803 _asn1_set_default_tag(ASN1_TYPE node
)
807 if((node
==NULL
) || (type_field(node
->type
)!=TYPE_DEFINITIONS
))
808 return ASN1_ELEMENT_NOT_FOUND
;
812 if((type_field(p
->type
)==TYPE_TAG
) &&
813 !(p
->type
&CONST_EXPLICIT
) &&
814 !(p
->type
&CONST_IMPLICIT
)){
815 if(node
->type
&CONST_EXPLICIT
) p
->type
|=CONST_EXPLICIT
;
816 else p
->type
|=CONST_IMPLICIT
;
822 else if(p
->right
) p
=p
->right
;
844 parse_version_number( const char *s
, int *number
)
848 if( *s
== '0' && isdigit(s
[1]) )
849 return NULL
; /* leading zeros are not allowed */
850 for ( ; isdigit(*s
); s
++ ) {
855 return val
< 0? NULL
: s
;
858 /* The parse version functions were copied from libgcrypt.
861 parse_version_string( const char *s
, int *major
, int *minor
, int *micro
)
863 s
= parse_version_number( s
, major
);
864 if( !s
|| *s
!= '.' )
867 s
= parse_version_number( s
, minor
);
868 if( !s
|| *s
!= '.' )
871 s
= parse_version_number( s
, micro
);
874 return s
; /* patchlevel */
878 * asn1_check_version - check for library version
879 * @req_version: Required version number, or NULL.
881 * Check that the the version of the library is at minimum the
882 * requested one and return the version string; return %NULL if the
883 * condition is not satisfied. If a %NULL is passed to this function,
884 * no check is done, but the version string is simply returned.
886 * See %LIBTASN1_VERSION for a suitable @req_version string.
888 * Return value: Version string of run-time library, or %NULL if the
889 * run-time library does not meet the required version number.
892 asn1_check_version( const char *req_version
)
894 const char *ver
= LIBTASN1_VERSION
;
895 int my_major
, my_minor
, my_micro
;
896 int rq_major
, rq_minor
, rq_micro
;
897 const char *my_plvl
, *rq_plvl
;
902 my_plvl
= parse_version_string( ver
, &my_major
, &my_minor
, &my_micro
);
904 return NULL
; /* very strange our own version is bogus */
905 rq_plvl
= parse_version_string( req_version
, &rq_major
, &rq_minor
,
908 return NULL
; /* req version string is invalid */
910 if ( my_major
> rq_major
911 || (my_major
== rq_major
&& my_minor
> rq_minor
)
912 || (my_major
== rq_major
&& my_minor
== rq_minor
913 && my_micro
> rq_micro
)
914 || (my_major
== rq_major
&& my_minor
== rq_minor
915 && my_micro
== rq_micro
916 && strcmp( my_plvl
, rq_plvl
) >= 0) ) {