2 * Copyright (C) 2000,2001 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
23 #include "parser_aux.h"
26 #include "structure.h"
29 char _asn1_identifierMissing
[MAX_NAME_SIZE
+1]; /* identifier name not found */
31 /***********************************************/
33 /* Description: type used in the list during */
34 /* the structure creation. */
35 /***********************************************/
36 typedef struct list_struct
{
38 struct list_struct
*next
;
42 /* Pointer to the first element of the list */
43 list_type
*firstElement
=NULL
;
45 /******************************************************/
46 /* Function : _asn1_add_node */
47 /* Description: creates a new NODE_ASN element and */
48 /* puts it in the list pointed by firstElement. */
50 /* type: type of the new element (see TYPE_ */
51 /* and CONST_ constants). */
52 /* Return: pointer to the new element. */
53 /******************************************************/
55 _asn1_add_node(unsigned int type
)
57 list_type
*listElement
;
60 punt
=(node_asn
*) _asn1_malloc(sizeof(node_asn
));
61 if (punt
==NULL
) return NULL
;
63 listElement
=(list_type
*) _asn1_malloc(sizeof(list_type
));
64 if(listElement
==NULL
){
69 listElement
->node
=punt
;
70 listElement
->next
=firstElement
;
71 firstElement
=listElement
;
83 /******************************************************************/
84 /* Function : _asn1_find_mode */
85 /* Description: searches an element called NAME starting from */
86 /* POINTER. The name is composed by differents */
87 /* identifiers separated by dots.When *POINTER has a */
88 /* name, the first identifier must be the name of */
89 /* *POINTER, otherwise it must be the name of one */
90 /* child of *POINTER. */
92 /* pointer: NODE_ASN element pointer. */
93 /* name: null terminated string with the element's name to find.*/
94 /* Return: the searching result. NULL if not find. */
95 /******************************************************************/
97 _asn1_find_node(node_asn
*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 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 /* previus 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
);
190 if(!len
) return node
;
191 node
->value
=(unsigned char *) _asn1_malloc(len
);
192 if (node
->value
==NULL
) return NULL
;
194 memcpy(node
->value
,value
,len
);
198 /******************************************************************/
199 /* Function : _asn1_set_name */
200 /* Description: sets the field NAME in a NODE_ASN element. The */
201 /* previus value (if exist) will be lost */
203 /* node: element pointer. */
204 /* name: a null terminated string with the name that you want */
206 /* Return: pointer to the NODE_ASN element. */
207 /******************************************************************/
209 _asn1_set_name(node_asn
*node
,const char *name
)
211 if(node
==NULL
) return node
;
214 _asn1_free(node
->name
);
218 if(name
==NULL
) return node
;
222 node
->name
=(char *) _asn1_strdup( name
);
223 if (node
->name
==NULL
) return NULL
;
225 else node
->name
=NULL
;
229 /******************************************************************/
230 /* Function : _asn1_set_right */
231 /* Description: sets the field RIGHT in a NODE_ASN element. */
233 /* node: element pointer. */
234 /* right: pointer to a NODE_ASN element that you want be pointed*/
236 /* Return: pointer to *NODE. */
237 /******************************************************************/
239 _asn1_set_right(node_asn
*node
,node_asn
*right
)
241 if(node
==NULL
) return node
;
243 if(right
) right
->left
=node
;
247 /******************************************************************/
248 /* Function : _asn1_get_right */
249 /* Description: returns the element pointed by the RIGHT field of */
250 /* a NODE_ASN element. */
252 /* node: NODE_ASN element pointer. */
253 /* Return: field RIGHT of NODE. */
254 /******************************************************************/
256 _asn1_get_right(node_asn
*node
)
258 if(node
==NULL
) return NULL
;
262 /******************************************************************/
263 /* Function : _asn1_get_last_right */
264 /* Description: return the last element along the right chain. */
266 /* node: starting element pointer. */
267 /* Return: pointer to the last element along the right chain. */
268 /******************************************************************/
270 _asn1_get_last_right(node_asn
*node
)
274 if(node
==NULL
) return NULL
;
276 while(p
->right
) p
=p
->right
;
280 /******************************************************************/
281 /* Function : _asn1_set_down */
282 /* Description: sets the field DOWN in a NODE_ASN element. */
284 /* node: element pointer. */
285 /* down: pointer to a NODE_ASN element that you want be pointed */
287 /* Return: pointer to *NODE. */
288 /******************************************************************/
290 _asn1_set_down(node_asn
*node
,node_asn
*down
)
292 if(node
==NULL
) return node
;
294 if(down
) down
->left
=node
;
298 /******************************************************************/
299 /* Function : _asn1_get_down */
300 /* Description: returns the element pointed by the DOWN field of */
301 /* a NODE_ASN element. */
303 /* node: NODE_ASN element pointer. */
304 /* Return: field DOWN of NODE. */
305 /******************************************************************/
307 _asn1_get_down(node_asn
*node
)
309 if(node
==NULL
) return NULL
;
313 /******************************************************************/
314 /* Function : _asn1_get_name */
315 /* Description: returns the name of a NODE_ASN element. */
317 /* node: NODE_ASN element pointer. */
318 /* Return: a null terminated string. */
319 /******************************************************************/
321 _asn1_get_name(node_asn
*node
)
323 if(node
==NULL
) return NULL
;
327 /******************************************************************/
328 /* Function : _asn1_mod_type */
329 /* Description: change the field TYPE of an NODE_ASN element. */
330 /* The new value is the old one | (bitwise or) the */
331 /* paramener VALUE. */
333 /* node: NODE_ASN element pointer. */
334 /* value: the integer value that must be or-ed with the current */
335 /* value of field TYPE. */
336 /* Return: NODE pointer. */
337 /******************************************************************/
339 _asn1_mod_type(node_asn
*node
,unsigned int value
)
341 if(node
==NULL
) return node
;
347 /******************************************************************/
348 /* Function : _asn1_remove_node */
349 /* Description: gets free the memory allocated for an NODE_ASN */
350 /* element (not the elements pointed by it). */
352 /* node: NODE_ASN element pointer. */
353 /******************************************************************/
355 _asn1_remove_node(node_asn
*node
)
357 if(node
==NULL
) return;
359 if (node
->name
!=NULL
)
360 _asn1_free(node
->name
);
361 if (node
->value
!=NULL
)
362 _asn1_free(node
->value
);
366 /******************************************************************/
367 /* Function : _asn1_find_up */
368 /* Description: return the father of the NODE_ASN element. */
370 /* node: NODE_ASN element pointer. */
371 /* Return: Null if not found. */
372 /******************************************************************/
374 _asn1_find_up(node_asn
*node
)
378 if(node
==NULL
) return NULL
;
382 while((p
->left
!=NULL
) && (p
->left
->right
==p
)) p
=p
->left
;
387 /******************************************************************/
388 /* Function : _asn1_delete_list */
389 /* Description: deletes the list elements (not the elements */
390 /* pointed by them). */
391 /******************************************************************/
393 _asn1_delete_list(void)
395 list_type
*listElement
;
398 listElement
=firstElement
;
399 firstElement
=firstElement
->next
;
400 _asn1_free(listElement
);
404 /******************************************************************/
405 /* Function : _asn1_delete_list_and nodes */
406 /* Description: deletes the list elements and the elements */
407 /* pointed by them. */
408 /******************************************************************/
410 _asn1_delete_list_and_nodes(void)
412 list_type
*listElement
;
415 listElement
=firstElement
;
416 firstElement
=firstElement
->next
;
417 _asn1_remove_node(listElement
->node
);
418 _asn1_free(listElement
);
424 _asn1_ltostr(long v
,char *str
)
441 temp
[start
+count
]='0'+(char)r
;
446 for(k
=0;k
<count
;k
++) str
[k
+start
]=temp
[start
+count
-k
-1];
452 /******************************************************************/
453 /* Function : _asn1_change_integer_value */
454 /* Description: converts into DER coding the value assign to an */
455 /* INTEGER constant. */
457 /* node: root of an ASN1element. */
459 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
460 /* otherwise ASN1_SUCCESS */
461 /******************************************************************/
463 _asn1_change_integer_value(ASN1_TYPE node
)
466 unsigned char val
[SIZEOF_UNSIGNED_LONG_INT
];
467 unsigned char val2
[SIZEOF_UNSIGNED_LONG_INT
+1];
470 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
474 if((type_field(p
->type
)==TYPE_INTEGER
) && (p
->type
&CONST_ASSIGN
)){
476 _asn1_convert_integer(p
->value
,val
,sizeof(val
), &len
);
477 _asn1_octet_der(val
,len
,val2
,&len
);
478 _asn1_set_value(p
,val2
,len
);
487 else if(p
->right
) p
=p
->right
;
508 /******************************************************************/
509 /* Function : _asn1_expand_object_id */
510 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
512 /* node: root of an ASN1 element. */
514 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
515 /* otherwise ASN1_SUCCESS */
516 /******************************************************************/
518 _asn1_expand_object_id(ASN1_TYPE node
)
520 node_asn
*p
,*p2
,*p3
,*p4
,*p5
;
521 char name_root
[MAX_NAME_SIZE
],name2
[2*MAX_NAME_SIZE
+1];
524 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
526 _asn1_str_cpy(name_root
, sizeof(name_root
), node
->name
);
531 while(!((p
==node
) && (move
==UP
))){
533 if((type_field(p
->type
)==TYPE_OBJECT_ID
) && (p
->type
&CONST_ASSIGN
)){
535 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
536 if(p2
->value
&& !isdigit(p2
->value
[0])){
537 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
538 _asn1_str_cat(name2
, sizeof(name2
), ".");
539 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
540 p3
=_asn1_find_node(node
,name2
);
541 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
542 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
543 _asn1_set_down(p
,p2
->right
);
544 _asn1_remove_node(p2
);
548 if(type_field(p4
->type
)==TYPE_CONSTANT
){
549 p5
=_asn1_add_node_only(TYPE_CONSTANT
);
550 _asn1_set_name(p5
,p4
->name
);
551 _asn1_set_value(p5
,p4
->value
,strlen(p4
->value
)+1);
553 _asn1_set_right(p5
,p
->down
);
554 _asn1_set_down(p
,p5
);
557 _asn1_set_right(p5
,p2
->right
);
558 _asn1_set_right(p2
,p5
);
574 if(p
->down
) p
=p
->down
;
578 if(p
==node
) {move
=UP
; continue;}
581 if(p
->right
) p
=p
->right
;
584 if(move
==UP
) p
=_asn1_find_up(p
);
588 /*******************************/
590 /*******************************/
594 while(!((p
==node
) && (move
==UP
))){
596 if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
597 (p
->type
&CONST_DEFAULT
)){
599 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
600 _asn1_str_cpy(name2
, sizeof(name2
), name_root
);
601 _asn1_str_cat(name2
, sizeof(name2
), ".");
602 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
603 p3
=_asn1_find_node(node
,name2
);
604 if(!p3
|| (type_field(p3
->type
)!=TYPE_OBJECT_ID
) ||
605 !(p3
->type
&CONST_ASSIGN
)) return ASN1_ELEMENT_NOT_FOUND
;
609 if(type_field(p4
->type
)==TYPE_CONSTANT
){
610 if(name2
[0]) _asn1_str_cat(name2
,sizeof(name2
),".");
611 _asn1_str_cat(name2
,sizeof(name2
),p4
->value
);
615 _asn1_set_value(p2
,name2
,strlen(name2
)+1);
623 if(p
->down
) p
=p
->down
;
627 if(p
==node
) {move
=UP
; continue;}
630 if(p
->right
) p
=p
->right
;
633 if(move
==UP
) p
=_asn1_find_up(p
);
640 /******************************************************************/
641 /* Function : _asn1_type_set_config */
642 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
643 /* in the fields of the SET elements. */
645 /* node: root of an ASN1 element. */
647 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
648 /* otherwise ASN1_SUCCESS */
649 /******************************************************************/
651 _asn1_type_set_config(ASN1_TYPE node
)
656 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
661 while(!((p
==node
) && (move
==UP
))){
663 if(type_field(p
->type
)==TYPE_SET
){
666 if(type_field(p2
->type
)!=TYPE_TAG
)
667 p2
->type
|=CONST_SET
|CONST_NOT_USED
;
676 if(p
->down
) p
=p
->down
;
680 if(p
==node
) {move
=UP
; continue;}
683 if(p
->right
) p
=p
->right
;
686 if(move
==UP
) p
=_asn1_find_up(p
);
693 /******************************************************************/
694 /* Function : _asn1_check_identifier */
695 /* Description: checks the definitions of all the identifiers */
696 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
697 /* The _asn1_identifierMissing global variable is filled if */
700 /* node: root of an ASN1 element. */
702 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
703 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
704 /* otherwise ASN1_SUCCESS */
705 /******************************************************************/
707 _asn1_check_identifier(ASN1_TYPE node
)
710 char name2
[MAX_NAME_SIZE
*2+2];
712 if(node
==NULL
) return ASN1_ELEMENT_NOT_FOUND
;
716 if(type_field(p
->type
)==TYPE_IDENTIFIER
){
717 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
718 _asn1_str_cat(name2
, sizeof(name2
), ".");
719 _asn1_str_cat(name2
, sizeof(name2
), p
->value
);
720 p2
=_asn1_find_node(node
,name2
);
722 strcpy(_asn1_identifierMissing
,p
->value
);
723 return ASN1_IDENTIFIER_NOT_FOUND
;
726 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
727 (p
->type
&CONST_DEFAULT
)){
729 if(p2
&& (type_field(p2
->type
)==TYPE_DEFAULT
)){
730 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
731 _asn1_str_cat(name2
, sizeof(name2
), ".");
732 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
733 strcpy(_asn1_identifierMissing
,p2
->value
);
734 p2
=_asn1_find_node(node
,name2
);
735 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
736 !(p2
->type
&CONST_ASSIGN
))
737 return ASN1_IDENTIFIER_NOT_FOUND
;
739 _asn1_identifierMissing
[0]=0;
742 else if((type_field(p
->type
)==TYPE_OBJECT_ID
) &&
743 (p
->type
&CONST_ASSIGN
)){
745 if(p2
&& (type_field(p2
->type
)==TYPE_CONSTANT
)){
746 if(p2
->value
&& !isdigit(p2
->value
[0])){
747 _asn1_str_cpy(name2
, sizeof(name2
), node
->name
);
748 _asn1_str_cat(name2
, sizeof(name2
), ".");
749 _asn1_str_cat(name2
, sizeof(name2
), p2
->value
);
750 strcpy(_asn1_identifierMissing
,p2
->value
);
751 p2
=_asn1_find_node(node
,name2
);
752 if(!p2
|| (type_field(p2
->type
)!=TYPE_OBJECT_ID
) ||
753 !(p2
->type
&CONST_ASSIGN
))
754 return ASN1_IDENTIFIER_NOT_FOUND
;
756 _asn1_identifierMissing
[0]=0;
764 else if(p
->right
) p
=p
->right
;
784 /******************************************************************/
785 /* Function : _asn1_set_default_tag */
786 /* Description: sets the default IMPLICIT or EXPLICIT property in */
787 /* the tagged elements that don't have this declaration. */
789 /* node: pointer to a DEFINITIONS element. */
791 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
792 /* a DEFINITIONS element, */
793 /* otherwise ASN1_SUCCESS */
794 /******************************************************************/
796 _asn1_set_default_tag(ASN1_TYPE node
)
800 if((node
==NULL
) || (type_field(node
->type
)!=TYPE_DEFINITIONS
))
801 return ASN1_ELEMENT_NOT_FOUND
;
805 if((type_field(p
->type
)==TYPE_TAG
) &&
806 !(p
->type
&CONST_EXPLICIT
) &&
807 !(p
->type
&CONST_IMPLICIT
)){
808 if(node
->type
&CONST_EXPLICIT
) p
->type
|=CONST_EXPLICIT
;
809 else p
->type
|=CONST_IMPLICIT
;
815 else if(p
->right
) p
=p
->right
;
837 parse_version_number( const char *s
, int *number
)
841 if( *s
== '0' && isdigit(s
[1]) )
842 return NULL
; /* leading zeros are not allowed */
843 for ( ; isdigit(*s
); s
++ ) {
848 return val
< 0? NULL
: s
;
851 /* The parse version functions were copied from libgcrypt.
854 parse_version_string( const char *s
, int *major
, int *minor
, int *micro
)
856 s
= parse_version_number( s
, major
);
857 if( !s
|| *s
!= '.' )
860 s
= parse_version_number( s
, minor
);
861 if( !s
|| *s
!= '.' )
864 s
= parse_version_number( s
, micro
);
867 return s
; /* patchlevel */
871 * asn1_check_version - This function checks the library's version
872 * @req_version: the version to check
874 * Check that the the version of the library is at minimum the requested one
875 * and return the version string; return NULL if the condition is not
876 * satisfied. If a NULL is passed to this function, no check is done,
877 * but the version string is simply returned.
881 asn1_check_version( const char *req_version
)
883 const char *ver
= LIBTASN1_VERSION
;
884 int my_major
, my_minor
, my_micro
;
885 int rq_major
, rq_minor
, rq_micro
;
886 const char *my_plvl
, *rq_plvl
;
891 my_plvl
= parse_version_string( ver
, &my_major
, &my_minor
, &my_micro
);
893 return NULL
; /* very strange our own version is bogus */
894 rq_plvl
= parse_version_string( req_version
, &rq_major
, &rq_minor
,
897 return NULL
; /* req version string is invalid */
899 if ( my_major
> rq_major
900 || (my_major
== rq_major
&& my_minor
> rq_minor
)
901 || (my_major
== rq_major
&& my_minor
== rq_minor
902 && my_micro
> rq_micro
)
903 || (my_major
== rq_major
&& my_minor
== rq_minor
904 && my_micro
== rq_micro
905 && strcmp( my_plvl
, rq_plvl
) >= 0) ) {