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
);
368 /******************************************************************/
369 /* Function : __asn1_find_up */
370 /* Description: return the father of the NODE_ASN element. */
372 /* node: NODE_ASN element pointer. */
373 /* Return: Null if not found. */
374 /******************************************************************/
376 __asn1_find_up(node_asn
*node
)
380 if(node
==NULL
) return NULL
;
384 while((p
->left
!=NULL
) && (p
->left
->right
==p
)) p
=p
->left
;
389 /******************************************************************/
390 /* Function : _asn1_delete_list */
391 /* Description: deletes the list elements (not the elements */
392 /* pointed by them). */
393 /******************************************************************/
395 _asn1_delete_list(void)
397 list_type
*listElement
;
400 listElement
=firstElement
;
401 firstElement
=firstElement
->next
;
402 _asn1_free(listElement
);
406 /******************************************************************/
407 /* Function : _asn1_delete_list_and nodes */
408 /* Description: deletes the list elements and the elements */
409 /* pointed by them. */
410 /******************************************************************/
412 _asn1_delete_list_and_nodes(void)
414 list_type
*listElement
;
417 listElement
=firstElement
;
418 firstElement
=firstElement
->next
;
419 _asn1_remove_node(listElement
->node
);
420 _asn1_free(listElement
);
426 _asn1_ltostr(long v
,char *str
)
443 temp
[start
+count
]='0'+(char)r
;
448 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
454 /******************************************************************/
455 /* Function : _asn1_change_integer_value */
456 /* Description: converts into DER coding the value assign to an */
457 /* INTEGER constant. */
459 /* node: root of an ASN1element. */
461 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
462 /* otherwise ASN1_SUCCESS */
463 /******************************************************************/
465 _asn1_change_integer_value(ASN1_TYPE node
)
468 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
469 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+1];
472 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
476 if((type_field(p
->type
)==TYPE_INTEGER
) && (p
->type
&CONST_ASSIGN
)){
478 _asn1_convert_integer(p
->value
,val
,sizeof(val
), &len
);
479 asn1_octet_der(val
,len
,val2
,&len
);
480 _asn1_set_value(p
,val2
,len
);
489 else if(p
->right
) p
=p
->right
;
510 /******************************************************************/
511 /* Function : _asn1_expand_object_id */
512 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
514 /* node: root of an ASN1 element. */
516 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
517 /* otherwise ASN1_SUCCESS */
518 /******************************************************************/
520 _asn1_expand_object_id(ASN1_TYPE node
)
522 node_asn
*p
,*p2
,*p3
,*p4
,*p5
;
523 char name_root
[MAX_NAME_SIZE
],name2
[2*MAX_NAME_SIZE
+1];
526 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
528 _asn1_str_cpy(name_root
, sizeof(name_root
), node
->name
);
533 while(!((p
==node
) && (move
==UP
))){
535 if((type_field(p
->type
)==TYPE_OBJECT_ID
) && (p
->type
&CONST_ASSIGN
)){
537 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
538 if(p2
->value
&& !isdigit(p2
->value
[0])){
539 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
540 _asn1_str_cat(name2
, sizeof(name2
), ".");
541 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
542 p3
=asn1_find_node(node
,name2
);
543 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
544 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
545 _asn1_set_down(p
,p2
->right
);
546 _asn1_remove_node(p2
);
550 if(type_field(p4
->type
)==TYPE_CONSTANT
){
551 p5
=_asn1_add_node_only(TYPE_CONSTANT
);
552 _asn1_set_name(p5
,p4
->name
);
553 tlen
= strlen( p4
->value
);
555 _asn1_set_value(p5
,p4
->value
,tlen
+1);
557 _asn1_set_right(p5
,p
->down
);
558 _asn1_set_down(p
,p5
);
561 _asn1_set_right(p5
,p2
->right
);
562 _asn1_set_right(p2
,p5
);
578 if(p
->down
) p
=p
->down
;
582 if(p
==node
) {move
=UP
; continue;}
585 if(p
->right
) p
=p
->right
;
588 if(move
==UP
) p
=_asn1_find_up(p
);
592 /*******************************/
594 /*******************************/
598 while(!((p
==node
) && (move
==UP
))){
600 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
601 (p
->type
&CONST_DEFAULT
)){
603 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
604 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
605 _asn1_str_cat(name2
, sizeof(name2
), ".");
606 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
607 p3
=asn1_find_node(node
,name2
);
608 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
609 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
613 if(type_field(p4
->type
)==TYPE_CONSTANT
){
614 if(name2
[0]) _asn1_str_cat(name2
,sizeof(name2
),".");
615 _asn1_str_cat(name2
,sizeof(name2
),p4
->value
);
619 tlen
= strlen(name2
);
621 _asn1_set_value(p2
,name2
,tlen
+1);
629 if(p
->down
) p
=p
->down
;
633 if(p
==node
) {move
=UP
; continue;}
636 if(p
->right
) p
=p
->right
;
639 if(move
==UP
) p
=_asn1_find_up(p
);
646 /******************************************************************/
647 /* Function : _asn1_type_set_config */
648 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
649 /* in the fields of the SET elements. */
651 /* node: root of an ASN1 element. */
653 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
654 /* otherwise ASN1_SUCCESS */
655 /******************************************************************/
657 _asn1_type_set_config(ASN1_TYPE node
)
662 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
667 while(!((p
==node
) && (move
==UP
))){
669 if(type_field(p
->type
)==TYPE_SET
){
672 if(type_field(p2
->type
)!=TYPE_TAG
)
673 p2
->type
|=CONST_SET
|CONST_NOT_USED
;
682 if(p
->down
) p
=p
->down
;
686 if(p
==node
) {move
=UP
; continue;}
689 if(p
->right
) p
=p
->right
;
692 if(move
==UP
) p
=_asn1_find_up(p
);
699 /******************************************************************/
700 /* Function : _asn1_check_identifier */
701 /* Description: checks the definitions of all the identifiers */
702 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
703 /* The _asn1_identifierMissing global variable is filled if */
706 /* node: root of an ASN1 element. */
708 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
709 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
710 /* otherwise ASN1_SUCCESS */
711 /******************************************************************/
713 _asn1_check_identifier(ASN1_TYPE node
)
716 char name2
[MAX_NAME_SIZE
*2+2];
718 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
722 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
723 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
724 _asn1_str_cat(name2
, sizeof(name2
), ".");
725 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
726 p2
=asn1_find_node(node
,name2
);
728 strcpy(_asn1_identifierMissing
,p
->value
);
729 return ASN1_IDENTIFIER_NOT_FOUND
;
732 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
733 (p
->type
&CONST_DEFAULT
)){
735 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
736 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
737 _asn1_str_cat(name2
, sizeof(name2
), ".");
738 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
739 strcpy(_asn1_identifierMissing
,p2
->value
);
740 p2
=asn1_find_node(node
,name2
);
741 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
742 !(p2
->type
&CONST_ASSIGN
))
743 return ASN1_IDENTIFIER_NOT_FOUND
;
745 _asn1_identifierMissing
[0]=0;
748 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
749 (p
->type
&CONST_ASSIGN
)){
751 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
752 if(p2
->value
&& !isdigit(p2
->value
[0])){
753 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
754 _asn1_str_cat(name2
, sizeof(name2
), ".");
755 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
756 strcpy(_asn1_identifierMissing
,p2
->value
);
757 p2
=asn1_find_node(node
,name2
);
758 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
759 !(p2
->type
&CONST_ASSIGN
))
760 return ASN1_IDENTIFIER_NOT_FOUND
;
762 _asn1_identifierMissing
[0]=0;
770 else if(p
->right
) p
=p
->right
;
790 /******************************************************************/
791 /* Function : _asn1_set_default_tag */
792 /* Description: sets the default IMPLICIT or EXPLICIT property in */
793 /* the tagged elements that don't have this declaration. */
795 /* node: pointer to a DEFINITIONS element. */
797 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
798 /* a DEFINITIONS element, */
799 /* otherwise ASN1_SUCCESS */
800 /******************************************************************/
802 _asn1_set_default_tag(ASN1_TYPE node
)
806 if((node
==NULL
) || (type_field(node
->type
)!=TYPE_DEFINITIONS
))
807 return ASN1_ELEMENT_NOT_FOUND
;
811 if((type_field(p
->type
)==TYPE_TAG
) &&
812 !(p
->type
&CONST_EXPLICIT
) &&
813 !(p
->type
&CONST_IMPLICIT
)){
814 if(node
->type
&CONST_EXPLICIT
) p
->type
|=CONST_EXPLICIT
;
815 else p
->type
|=CONST_IMPLICIT
;
821 else if(p
->right
) p
=p
->right
;
843 parse_version_number( const char *s
, int *number
)
847 if( *s
== '0' && isdigit(s
[1]) )
848 return NULL
; /* leading zeros are not allowed */
849 for ( ; isdigit(*s
); s
++ ) {
854 return val
< 0? NULL
: s
;
857 /* The parse version functions were copied from libgcrypt.
860 parse_version_string( const char *s
, int *major
, int *minor
, int *micro
)
862 s
= parse_version_number( s
, major
);
863 if( !s
|| *s
!= '.' )
866 s
= parse_version_number( s
, minor
);
867 if( !s
|| *s
!= '.' )
870 s
= parse_version_number( s
, micro
);
873 return s
; /* patchlevel */
877 * asn1_check_version - check for library version
878 * @req_version: Required version number, or NULL.
880 * Check that the the version of the library is at minimum the
881 * requested one and return the version string; return %NULL if the
882 * condition is not satisfied. If a %NULL is passed to this function,
883 * no check is done, but the version string is simply returned.
885 * See %LIBTASN1_VERSION for a suitable @req_version string.
887 * Return value: Version string of run-time library, or %NULL if the
888 * run-time library does not meet the required version number.
891 asn1_check_version( const char *req_version
)
893 const char *ver
= LIBTASN1_VERSION
;
894 int my_major
, my_minor
, my_micro
;
895 int rq_major
, rq_minor
, rq_micro
;
896 const char *my_plvl
, *rq_plvl
;
901 my_plvl
= parse_version_string( ver
, &my_major
, &my_minor
, &my_micro
);
903 return NULL
; /* very strange our own version is bogus */
904 rq_plvl
= parse_version_string( req_version
, &rq_major
, &rq_minor
,
907 return NULL
; /* req version string is invalid */
909 if ( my_major
> rq_major
910 || (my_major
== rq_major
&& my_minor
> rq_minor
)
911 || (my_major
== rq_major
&& my_minor
== rq_minor
912 && my_micro
> rq_micro
)
913 || (my_major
== rq_major
&& my_minor
== rq_minor
914 && my_micro
== rq_micro
915 && strcmp( my_plvl
, rq_plvl
) >= 0) ) {