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"
28 #include "structure.h"
31 char _asn1_identifierMissing[MAX_NAME_SIZE+1]; /* identifier name not found */
33 /***********************************************/
35 /* Description: type used in the list during */
36 /* the structure creation. */
37 /***********************************************/
38 typedef struct list_struct{
40 struct list_struct *next;
44 /* Pointer to the first element of the list */
45 list_type *firstElement=NULL;
47 /******************************************************/
48 /* Function : _asn1_add_node */
49 /* Description: creates a new NODE_ASN element and */
50 /* puts it in the list pointed by firstElement. */
52 /* type: type of the new element (see TYPE_ */
53 /* and CONST_ constants). */
54 /* Return: pointer to the new element. */
55 /******************************************************/
57 _asn1_add_node(unsigned int type)
59 list_type *listElement;
62 punt=(node_asn *) _asn1_malloc(sizeof(node_asn));
63 if (punt==NULL) return NULL;
65 listElement=(list_type *) _asn1_malloc(sizeof(list_type));
66 if(listElement==NULL){
71 listElement->node=punt;
72 listElement->next=firstElement;
73 firstElement=listElement;
85 /******************************************************************/
86 /* Function : _asn1_find_mode */
87 /* Description: searches an element called NAME starting from */
88 /* POINTER. The name is composed by differents */
89 /* identifiers separated by dots.When *POINTER has a */
90 /* name, the first identifier must be the name of */
91 /* *POINTER, otherwise it must be the name of one */
92 /* child of *POINTER. */
94 /* pointer: NODE_ASN element pointer. */
95 /* name: null terminated string with the element's name to find.*/
96 /* Return: the searching result. NULL if not found. */
97 /******************************************************************/
99 _asn1_find_node(node_asn *pointer,const char *name)
102 char *n_end,n[MAX_NAME_SIZE+1];
105 if(pointer == NULL) return NULL;
107 if(name==NULL) return NULL;
112 if(p->name != NULL){ /* has *pointer got a name ? */
113 n_end=strchr(n_start,'.'); /* search the first dot */
115 memcpy(n,n_start,n_end-n_start);
121 _asn1_str_cpy(n,sizeof(n),n_start);
126 if((p->name) && (!strcmp(p->name,n))) break;
130 if(p==NULL) return NULL;
132 else{ /* *pointer doesn't have a name */
137 while(n_start){ /* Has the end of NAME been reached? */
138 n_end=strchr(n_start,'.'); /* search the next dot */
140 memcpy(n,n_start,n_end-n_start);
146 _asn1_str_cpy(n,sizeof(n),n_start);
150 if(p->down==NULL) return NULL;
154 /* The identifier "?LAST" indicates the last element
155 in the right chain. */
156 if(!strcmp(n,"?LAST")){
157 if(p==NULL) return NULL;
158 while(p->right) p=p->right;
160 else{ /* no "?LAST" */
162 if((p->name) && (!strcmp(p->name,n))) break;
165 if(p==NULL) return NULL;
173 /******************************************************************/
174 /* Function : _asn1_set_value */
175 /* Description: sets the field VALUE in a NODE_ASN element. The */
176 /* previous value (if exist) will be lost */
178 /* node: element pointer. */
179 /* value: pointer to the value that you want to set. */
180 /* len: character number of value. */
181 /* Return: pointer to the NODE_ASN element. */
182 /******************************************************************/
184 _asn1_set_value(node_asn *node,const unsigned char *value,unsigned int len)
187 if(node==NULL) return node;
189 _asn1_free(node->value);
193 if(!len) return node;
194 node->value=(unsigned char *) _asn1_malloc(len);
195 if (node->value==NULL) return NULL;
196 node->value_len = len;
198 memcpy(node->value,value,len);
202 /******************************************************************/
203 /* Function : _asn1_set_name */
204 /* Description: sets the field NAME in a NODE_ASN element. The */
205 /* previous value (if exist) will be lost */
207 /* node: element pointer. */
208 /* name: a null terminated string with the name that you want */
210 /* Return: pointer to the NODE_ASN element. */
211 /******************************************************************/
213 _asn1_set_name(node_asn *node,const char *name)
215 if(node==NULL) return node;
218 _asn1_free(node->name);
222 if(name==NULL) return node;
226 node->name=(char *) _asn1_strdup( name);
227 if (node->name==NULL) return NULL;
229 else node->name=NULL;
233 /******************************************************************/
234 /* Function : _asn1_set_right */
235 /* Description: sets the field RIGHT in a NODE_ASN element. */
237 /* node: element pointer. */
238 /* right: pointer to a NODE_ASN element that you want be pointed*/
240 /* Return: pointer to *NODE. */
241 /******************************************************************/
243 _asn1_set_right(node_asn *node,node_asn *right)
245 if(node==NULL) return node;
247 if(right) right->left=node;
251 /******************************************************************/
252 /* Function : _asn1_get_right */
253 /* Description: returns the element pointed by the RIGHT field of */
254 /* a NODE_ASN element. */
256 /* node: NODE_ASN element pointer. */
257 /* Return: field RIGHT of NODE. */
258 /******************************************************************/
260 _asn1_get_right(node_asn *node)
262 if(node==NULL) return NULL;
266 /******************************************************************/
267 /* Function : _asn1_get_last_right */
268 /* Description: return the last element along the right chain. */
270 /* node: starting element pointer. */
271 /* Return: pointer to the last element along the right chain. */
272 /******************************************************************/
274 _asn1_get_last_right(node_asn *node)
278 if(node==NULL) return NULL;
280 while(p->right) p=p->right;
284 /******************************************************************/
285 /* Function : _asn1_set_down */
286 /* Description: sets the field DOWN in a NODE_ASN element. */
288 /* node: element pointer. */
289 /* down: pointer to a NODE_ASN element that you want be pointed */
291 /* Return: pointer to *NODE. */
292 /******************************************************************/
294 _asn1_set_down(node_asn *node,node_asn *down)
296 if(node==NULL) return node;
298 if(down) down->left=node;
302 /******************************************************************/
303 /* Function : _asn1_get_down */
304 /* Description: returns the element pointed by the DOWN field of */
305 /* a NODE_ASN element. */
307 /* node: NODE_ASN element pointer. */
308 /* Return: field DOWN of NODE. */
309 /******************************************************************/
311 _asn1_get_down(node_asn *node)
313 if(node==NULL) return NULL;
317 /******************************************************************/
318 /* Function : _asn1_get_name */
319 /* Description: returns the name of a NODE_ASN element. */
321 /* node: NODE_ASN element pointer. */
322 /* Return: a null terminated string. */
323 /******************************************************************/
325 _asn1_get_name(node_asn *node)
327 if(node==NULL) return NULL;
331 /******************************************************************/
332 /* Function : _asn1_mod_type */
333 /* Description: change the field TYPE of an NODE_ASN element. */
334 /* The new value is the old one | (bitwise or) the */
335 /* paramener VALUE. */
337 /* node: NODE_ASN element pointer. */
338 /* value: the integer value that must be or-ed with the current */
339 /* value of field TYPE. */
340 /* Return: NODE pointer. */
341 /******************************************************************/
343 _asn1_mod_type(node_asn *node,unsigned int value)
345 if(node==NULL) return node;
351 /******************************************************************/
352 /* Function : _asn1_remove_node */
353 /* Description: gets free the memory allocated for an NODE_ASN */
354 /* element (not the elements pointed by it). */
356 /* node: NODE_ASN element pointer. */
357 /******************************************************************/
359 _asn1_remove_node(node_asn *node)
361 if(node==NULL) return;
363 if (node->name!=NULL)
364 _asn1_free(node->name);
365 if (node->value!=NULL)
366 _asn1_free(node->value);
370 /******************************************************************/
371 /* Function : _asn1_find_up */
372 /* Description: return the father of the NODE_ASN element. */
374 /* node: NODE_ASN element pointer. */
375 /* Return: Null if not found. */
376 /******************************************************************/
378 _asn1_find_up(node_asn *node)
382 if(node==NULL) return NULL;
386 while((p->left!=NULL) && (p->left->right==p)) p=p->left;
391 /******************************************************************/
392 /* Function : _asn1_delete_list */
393 /* Description: deletes the list elements (not the elements */
394 /* pointed by them). */
395 /******************************************************************/
397 _asn1_delete_list(void)
399 list_type *listElement;
402 listElement=firstElement;
403 firstElement=firstElement->next;
404 _asn1_free(listElement);
408 /******************************************************************/
409 /* Function : _asn1_delete_list_and nodes */
410 /* Description: deletes the list elements and the elements */
411 /* pointed by them. */
412 /******************************************************************/
414 _asn1_delete_list_and_nodes(void)
416 list_type *listElement;
419 listElement=firstElement;
420 firstElement=firstElement->next;
421 _asn1_remove_node(listElement->node);
422 _asn1_free(listElement);
428 _asn1_ltostr(long v,char *str)
445 temp[start+count]='0'+(char)r;
450 for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1];
456 /******************************************************************/
457 /* Function : _asn1_change_integer_value */
458 /* Description: converts into DER coding the value assign to an */
459 /* INTEGER constant. */
461 /* node: root of an ASN1element. */
463 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
464 /* otherwise ASN1_SUCCESS */
465 /******************************************************************/
467 _asn1_change_integer_value(ASN1_TYPE node)
470 unsigned char val[SIZEOF_UNSIGNED_LONG_INT];
471 unsigned char val2[SIZEOF_UNSIGNED_LONG_INT+1];
474 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
478 if((type_field(p->type)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){
480 _asn1_convert_integer(p->value,val,sizeof(val), &len);
481 _asn1_octet_der(val,len,val2,&len);
482 _asn1_set_value(p,val2,len);
491 else if(p->right) p=p->right;
512 /******************************************************************/
513 /* Function : _asn1_expand_object_id */
514 /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */
516 /* node: root of an ASN1 element. */
518 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
519 /* otherwise ASN1_SUCCESS */
520 /******************************************************************/
522 _asn1_expand_object_id(ASN1_TYPE node)
524 node_asn *p,*p2,*p3,*p4,*p5;
525 char name_root[MAX_NAME_SIZE],name2[2*MAX_NAME_SIZE+1];
528 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
530 _asn1_str_cpy(name_root, sizeof(name_root), node->name);
535 while(!((p==node) && (move==UP))){
537 if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){
539 if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
540 if(p2->value && !isdigit(p2->value[0])){
541 _asn1_str_cpy(name2, sizeof(name2), name_root);
542 _asn1_str_cat(name2, sizeof(name2), ".");
543 _asn1_str_cat(name2, sizeof(name2), p2->value);
544 p3=_asn1_find_node(node,name2);
545 if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) ||
546 !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND;
547 _asn1_set_down(p,p2->right);
548 _asn1_remove_node(p2);
552 if(type_field(p4->type)==TYPE_CONSTANT){
553 p5=_asn1_add_node_only(TYPE_CONSTANT);
554 _asn1_set_name(p5,p4->name);
555 tlen = strlen( p4->value);
557 _asn1_set_value(p5,p4->value,tlen+1);
559 _asn1_set_right(p5,p->down);
560 _asn1_set_down(p,p5);
563 _asn1_set_right(p5,p2->right);
564 _asn1_set_right(p2,p5);
580 if(p->down) p=p->down;
584 if(p==node) {move=UP; continue;}
587 if(p->right) p=p->right;
590 if(move==UP) p=_asn1_find_up(p);
594 /*******************************/
596 /*******************************/
600 while(!((p==node) && (move==UP))){
602 if((type_field(p->type)==TYPE_OBJECT_ID) &&
603 (p->type&CONST_DEFAULT)){
605 if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){
606 _asn1_str_cpy(name2, sizeof(name2), name_root);
607 _asn1_str_cat(name2, sizeof(name2), ".");
608 _asn1_str_cat(name2, sizeof(name2), p2->value);
609 p3=_asn1_find_node(node,name2);
610 if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) ||
611 !(p3->type&CONST_ASSIGN)) return ASN1_ELEMENT_NOT_FOUND;
615 if(type_field(p4->type)==TYPE_CONSTANT){
616 if(name2[0]) _asn1_str_cat(name2,sizeof(name2),".");
617 _asn1_str_cat(name2,sizeof(name2),p4->value);
621 tlen = strlen(name2);
623 _asn1_set_value(p2,name2,tlen+1);
631 if(p->down) p=p->down;
635 if(p==node) {move=UP; continue;}
638 if(p->right) p=p->right;
641 if(move==UP) p=_asn1_find_up(p);
648 /******************************************************************/
649 /* Function : _asn1_type_set_config */
650 /* Description: sets the CONST_SET and CONST_NOT_USED properties */
651 /* in the fields of the SET elements. */
653 /* node: root of an ASN1 element. */
655 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
656 /* otherwise ASN1_SUCCESS */
657 /******************************************************************/
659 _asn1_type_set_config(ASN1_TYPE node)
664 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
669 while(!((p==node) && (move==UP))){
671 if(type_field(p->type)==TYPE_SET){
674 if(type_field(p2->type)!=TYPE_TAG)
675 p2->type|=CONST_SET|CONST_NOT_USED;
684 if(p->down) p=p->down;
688 if(p==node) {move=UP; continue;}
691 if(p->right) p=p->right;
694 if(move==UP) p=_asn1_find_up(p);
701 /******************************************************************/
702 /* Function : _asn1_check_identifier */
703 /* Description: checks the definitions of all the identifiers */
704 /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */
705 /* The _asn1_identifierMissing global variable is filled if */
708 /* node: root of an ASN1 element. */
710 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */
711 /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */
712 /* otherwise ASN1_SUCCESS */
713 /******************************************************************/
715 _asn1_check_identifier(ASN1_TYPE node)
718 char name2[MAX_NAME_SIZE*2+2];
720 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
724 if(type_field(p->type)==TYPE_IDENTIFIER){
725 _asn1_str_cpy(name2, sizeof(name2), node->name);
726 _asn1_str_cat(name2, sizeof(name2), ".");
727 _asn1_str_cat(name2, sizeof(name2), p->value);
728 p2=_asn1_find_node(node,name2);
730 strcpy(_asn1_identifierMissing,p->value);
731 return ASN1_IDENTIFIER_NOT_FOUND;
734 else if((type_field(p->type)==TYPE_OBJECT_ID) &&
735 (p->type&CONST_DEFAULT)){
737 if(p2 && (type_field(p2->type)==TYPE_DEFAULT)){
738 _asn1_str_cpy(name2, sizeof(name2), node->name);
739 _asn1_str_cat(name2, sizeof(name2), ".");
740 _asn1_str_cat(name2, sizeof(name2), p2->value);
741 strcpy(_asn1_identifierMissing,p2->value);
742 p2=_asn1_find_node(node,name2);
743 if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
744 !(p2->type&CONST_ASSIGN))
745 return ASN1_IDENTIFIER_NOT_FOUND;
747 _asn1_identifierMissing[0]=0;
750 else if((type_field(p->type)==TYPE_OBJECT_ID) &&
751 (p->type&CONST_ASSIGN)){
753 if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){
754 if(p2->value && !isdigit(p2->value[0])){
755 _asn1_str_cpy(name2, sizeof(name2), node->name);
756 _asn1_str_cat(name2, sizeof(name2), ".");
757 _asn1_str_cat(name2, sizeof(name2), p2->value);
758 strcpy(_asn1_identifierMissing,p2->value);
759 p2=_asn1_find_node(node,name2);
760 if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) ||
761 !(p2->type&CONST_ASSIGN))
762 return ASN1_IDENTIFIER_NOT_FOUND;
764 _asn1_identifierMissing[0]=0;
772 else if(p->right) p=p->right;
792 /******************************************************************/
793 /* Function : _asn1_set_default_tag */
794 /* Description: sets the default IMPLICIT or EXPLICIT property in */
795 /* the tagged elements that don't have this declaration. */
797 /* node: pointer to a DEFINITIONS element. */
799 /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */
800 /* a DEFINITIONS element, */
801 /* otherwise ASN1_SUCCESS */
802 /******************************************************************/
804 _asn1_set_default_tag(ASN1_TYPE node)
808 if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS))
809 return ASN1_ELEMENT_NOT_FOUND;
813 if((type_field(p->type)==TYPE_TAG) &&
814 !(p->type&CONST_EXPLICIT) &&
815 !(p->type&CONST_IMPLICIT)){
816 if(node->type&CONST_EXPLICIT) p->type|=CONST_EXPLICIT;
817 else p->type|=CONST_IMPLICIT;
823 else if(p->right) p=p->right;
845 parse_version_number( const char *s, int *number )
849 if( *s == '0' && isdigit(s[1]) )
850 return NULL; /* leading zeros are not allowed */
851 for ( ; isdigit(*s); s++ ) {
856 return val < 0? NULL : s;
859 /* The parse version functions were copied from libgcrypt.
862 parse_version_string( const char *s, int *major, int *minor, int *micro )
864 s = parse_version_number( s, major );
865 if( !s || *s != '.' )
868 s = parse_version_number( s, minor );
869 if( !s || *s != '.' )
872 s = parse_version_number( s, micro );
875 return s; /* patchlevel */
879 * asn1_check_version - check for library version
880 * @req_version: Required version number, or NULL.
882 * Check that the the version of the library is at minimum the
883 * requested one and return the version string; return %NULL if the
884 * condition is not satisfied. If a %NULL is passed to this function,
885 * no check is done, but the version string is simply returned.
887 * See %LIBTASN1_VERSION for a suitable @req_version string.
889 * Return value: Version string of run-time library, or %NULL if the
890 * run-time library does not meet the required version number.
893 asn1_check_version( const char *req_version )
895 const char *ver = LIBTASN1_VERSION;
896 int my_major, my_minor, my_micro;
897 int rq_major, rq_minor, rq_micro;
898 const char *my_plvl, *rq_plvl;
903 my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro );
905 return NULL; /* very strange our own version is bogus */
906 rq_plvl = parse_version_string( req_version, &rq_major, &rq_minor,
909 return NULL; /* req version string is invalid */
911 if ( my_major > rq_major
912 || (my_major == rq_major && my_minor > rq_minor)
913 || (my_major == rq_major && my_minor == rq_minor
914 && my_micro > rq_micro)
915 || (my_major == rq_major && my_minor == rq_minor
916 && my_micro == rq_micro
917 && strcmp( my_plvl, rq_plvl ) >= 0) ) {