diff options
author | Fabio Fiorina <fiorinaf@gnutls.org> | 2002-05-15 19:33:44 +0000 |
---|---|---|
committer | Fabio Fiorina <fiorinaf@gnutls.org> | 2002-05-15 19:33:44 +0000 |
commit | 312b5267bfb51508975b8032c316fa9e20686f2b (patch) | |
tree | e79ea003e9d6e970ec123cd0fbf6339e1256ce1c /lib | |
parent | 3d9221565c51fe3006546fb14e0738cbb011e24c (diff) | |
download | libtasn1-312b5267bfb51508975b8032c316fa9e20686f2b.tar.gz libtasn1-312b5267bfb51508975b8032c316fa9e20686f2b.tar.bz2 libtasn1-312b5267bfb51508975b8032c316fa9e20686f2b.zip |
Start Up Version
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ASN.y | 600 | ||||
-rw-r--r-- | lib/Makefile.am | 11 | ||||
-rw-r--r-- | lib/asn1.c | 1985 | ||||
-rw-r--r-- | lib/asn1.h | 204 | ||||
-rw-r--r-- | lib/defines.h | 16 | ||||
-rw-r--r-- | lib/der.c | 1417 | ||||
-rw-r--r-- | lib/der.h | 56 | ||||
-rw-r--r-- | lib/gstr.c | 17 | ||||
-rw-r--r-- | lib/mem.h | 2 |
9 files changed, 64 insertions, 4244 deletions
diff --git a/lib/ASN.y b/lib/ASN.y deleted file mode 100644 index 00ce4cf..0000000 --- a/lib/ASN.y +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright (C) 2000,2001 Fabio Fiorina - * - * This file is part of GNUTLS. - * - * GNUTLS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUTLS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - - -/*****************************************************/ -/* File: x509_ASN.y */ -/* Description: input file for 'bison' program. */ -/* The output file is a parser (in C language) for */ -/* ASN.1 syntax */ -/*****************************************************/ - - -%{ -#include <defines.h> -#include <asn1.h> - -FILE *file_asn1; /* Pointer to file to parse */ -extern int parse_mode; /* PARSE_MODE_CHECK = only syntax check - PARSE_MODE_CREATE = structure creation */ -int result_parse; /* result of the parser algorithm */ -node_asn *p_tree; /* pointer to the root of the structure - created by the parser*/ - -int yyerror (char *); -int yylex(void); - -%} - - -%union { - unsigned int constant; - char str[129]; - node_asn* node; -} - - -%token ASSIG "::=" -%token <str> NUM -%token <str> IDENTIFIER -%token OPTIONAL -%token INTEGER -%token SIZE -%token OCTET -%token STRING -%token SEQUENCE -%token BIT -%token UNIVERSAL -%token PRIVATE -%token APPLICATION -%token OPTIONAL -%token DEFAULT -%token CHOICE -%token OF -%token OBJECT -%token STR_IDENTIFIER -%token BOOLEAN -%token TRUE -%token FALSE -%token TOKEN_NULL -%token ANY -%token DEFINED -%token BY -%token SET -%token EXPLICIT -%token IMPLICIT -%token DEFINITIONS -%token TAGS -%token BEGIN -%token END -%token UTCTime -%token GeneralizedTime -%token FROM -%token IMPORTS -%token ENUMERATED - -%type <node> octet_string_def constant constant_list type_assig_right -%type <node> integer_def type_assig type_assig_list sequence_def type_def -%type <node> bit_string_def default size_def choise_def object_def -%type <node> boolean_def any_def size_def2 obj_constant obj_constant_list -%type <node> constant_def type_constant type_constant_list definitions -%type <node> definitions_id Time bit_element bit_element_list set_def -%type <node> identifier_list imports_def tag_type tag type_assig_right_tag -%type <node> type_assig_right_tag_default enumerated_def -%type <str> pos_num neg_num pos_neg_num pos_neg_identifier num_identifier -%type <constant> class explicit_implicit - -%% - -input: /* empty */ - | input definitions -; - -pos_num : NUM {strcpy($$,$1);} - | '+' NUM {strcpy($$,$2);} -; - -neg_num : '-' NUM {strcpy($$,"-"); - strcat($$,$2);} -; - -pos_neg_num : pos_num {strcpy($$,$1);} - | neg_num {strcpy($$,$1);} -; - -num_identifier : NUM {strcpy($$,$1);} - | IDENTIFIER {strcpy($$,$1);} -; - -pos_neg_identifier : pos_neg_num {strcpy($$,$1);} - | IDENTIFIER {strcpy($$,$1);} -; - -constant: '(' pos_neg_num ')' {$$=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_value($$,$2,strlen($2)+1);} - | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_name($$,$1); - _asn1_set_value($$,$3,strlen($3)+1);} -; - -constant_list: constant {$$=$1;} - | constant_list ',' constant {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$3);} -; - -identifier_list : IDENTIFIER {$$=_asn1_add_node(TYPE_IDENTIFIER); - _asn1_set_name($$,$1);} - | identifier_list IDENTIFIER - {$$=$1; - _asn1_set_right(_asn1_get_last_right($$),_asn1_add_node(TYPE_IDENTIFIER)); - _asn1_set_name(_asn1_get_last_right($$),$2);} -; - -obj_constant: num_identifier {$$=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_value($$,$1,strlen($1)+1);} - | IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_name($$,$1); - _asn1_set_value($$,$3,strlen($3)+1);} -; - -obj_constant_list: obj_constant {$$=$1;} - | obj_constant_list obj_constant {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$2);} -; - -class : UNIVERSAL {$$=CONST_UNIVERSAL;} - | PRIVATE {$$=CONST_PRIVATE;} - | APPLICATION {$$=CONST_APPLICATION;} -; - -tag_type : '[' NUM ']' {$$=_asn1_add_node(TYPE_TAG); - _asn1_set_value($$,$2,strlen($2)+1);} - | '[' class NUM ']' {$$=_asn1_add_node(TYPE_TAG | $2); - _asn1_set_value($$,$3,strlen($3)+1);} -; - -tag : tag_type {$$=$1;} - | tag_type EXPLICIT {$$=_asn1_mod_type($1,CONST_EXPLICIT);} - | tag_type IMPLICIT {$$=_asn1_mod_type($1,CONST_IMPLICIT);} -; - -default : DEFAULT pos_neg_identifier {$$=_asn1_add_node(TYPE_DEFAULT); - _asn1_set_value($$,$2,strlen($2)+1);} - | DEFAULT TRUE {$$=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);} - | DEFAULT FALSE {$$=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);} -; - -integer_def: INTEGER {$$=_asn1_add_node(TYPE_INTEGER);} - | INTEGER'{'constant_list'}' {$$=_asn1_add_node(TYPE_INTEGER|CONST_LIST); - _asn1_set_down($$,$3);} - | integer_def'('num_identifier'.''.'num_identifier')' - {$$=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX); - _asn1_set_down($$,_asn1_add_node(TYPE_SIZE)); - _asn1_set_value(_asn1_get_down($$),$6,strlen($6)+1); - _asn1_set_name(_asn1_get_down($$),$3);} -; - -boolean_def: BOOLEAN {$$=_asn1_add_node(TYPE_BOOLEAN);} -; - -Time: UTCTime {$$=_asn1_add_node(TYPE_TIME|CONST_UTC);} - | GeneralizedTime {$$=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);} -; - -size_def2: SIZE'('num_identifier')' {$$=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM); - _asn1_set_value($$,$3,strlen($3)+1);} - | SIZE'('num_identifier'.''.'num_identifier')' - {$$=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX); - _asn1_set_value($$,$3,strlen($3)+1); - _asn1_set_name($$,$6);} -; - -size_def: size_def2 {$$=$1;} - | '(' size_def2 ')' {$$=$2;} -; - -octet_string_def : OCTET STRING {$$=_asn1_add_node(TYPE_OCTET_STRING);} - | OCTET STRING size_def {$$=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE); - _asn1_set_down($$,$3);} -; - -bit_element : IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_name($$,$1); - _asn1_set_value($$,$3,strlen($3)+1);} -; - -bit_element_list : bit_element {$$=$1;} - | bit_element_list ',' bit_element {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$3);} -; - -bit_string_def : BIT STRING {$$=_asn1_add_node(TYPE_BIT_STRING);} - | BIT STRING'{'bit_element_list'}' - {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST); - _asn1_set_down($$,$4);} -; - -enumerated_def : ENUMERATED'{'bit_element_list'}' - {$$=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST); - _asn1_set_down($$,$3);} -; - -object_def : OBJECT STR_IDENTIFIER {$$=_asn1_add_node(TYPE_OBJECT_ID);} -; - -type_assig_right: IDENTIFIER {$$=_asn1_add_node(TYPE_IDENTIFIER); - _asn1_set_value($$,$1,strlen($1)+1);} - | IDENTIFIER size_def {$$=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE); - _asn1_set_value($$,$1,strlen($1)+1); - _asn1_set_down($$,$2);} - | integer_def {$$=$1;} - | enumerated_def {$$=$1;} - | boolean_def {$$=$1;} - | Time - | octet_string_def {$$=$1;} - | bit_string_def {$$=$1;} - | sequence_def {$$=$1;} - | object_def {$$=$1;} - | choise_def {$$=$1;} - | any_def {$$=$1;} - | set_def {$$=$1;} - | TOKEN_NULL {$$=_asn1_add_node(TYPE_NULL);} -; - -type_assig_right_tag : type_assig_right {$$=$1;} - | tag type_assig_right {$$=_asn1_mod_type($2,CONST_TAG); - _asn1_set_right($1,_asn1_get_down($$)); - _asn1_set_down($$,$1);} -; - -type_assig_right_tag_default : type_assig_right_tag {$$=$1;} - | type_assig_right_tag default {$$=_asn1_mod_type($1,CONST_DEFAULT); - _asn1_set_right($2,_asn1_get_down($$)); - _asn1_set_down($$,$2);} - | type_assig_right_tag OPTIONAL {$$=_asn1_mod_type($1,CONST_OPTION);} -; - -type_assig : IDENTIFIER type_assig_right_tag_default {$$=_asn1_set_name($2,$1);} -; - -type_assig_list : type_assig {$$=$1;} - | type_assig_list','type_assig {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$3);} -; - -sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SEQUENCE); - _asn1_set_down($$,$3);} - | SEQUENCE OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF); - _asn1_set_down($$,$3);} - | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE); - _asn1_set_right($2,$4); - _asn1_set_down($$,$2);} -; - -set_def : SET'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SET); - _asn1_set_down($$,$3);} - | SET OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF); - _asn1_set_down($$,$3);} - | SET size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF|CONST_SIZE); - _asn1_set_right($2,$4); - _asn1_set_down($$,$2);} -; - -choise_def : CHOICE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_CHOICE); - _asn1_set_down($$,$3);} -; - -any_def : ANY {$$=_asn1_add_node(TYPE_ANY);} - | ANY DEFINED BY IDENTIFIER {$$=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY); - _asn1_set_down($$,_asn1_add_node(TYPE_CONSTANT)); - _asn1_set_name(_asn1_get_down($$),$4);} -; - -type_def : IDENTIFIER "::=" type_assig_right_tag {$$=_asn1_set_name($3,$1);} -; - -constant_def : IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}' - {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN); - _asn1_set_name($$,$1); - _asn1_set_down($$,$6);} - | IDENTIFIER IDENTIFIER "::=" '{' obj_constant_list '}' - {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM); - _asn1_set_name($$,$1); - _asn1_set_value($$,$2,strlen($2)+1); - _asn1_set_down($$,$5);} - | IDENTIFIER INTEGER "::=" NUM - {$$=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN); - _asn1_set_name($$,$1); - _asn1_set_value($$,$4,strlen($4)+1);} -; - -type_constant: type_def {$$=$1;} - | constant_def {$$=$1;} -; - -type_constant_list : type_constant {$$=$1;} - | type_constant_list type_constant {$$=$1; - _asn1_set_right(_asn1_get_last_right($1),$2);} -; - -definitions_id : IDENTIFIER '{' obj_constant_list '}' {$$=_asn1_add_node(TYPE_OBJECT_ID); - _asn1_set_down($$,$3); - _asn1_set_name($$,$1);} - | IDENTIFIER '{' '}' {$$=_asn1_add_node(TYPE_OBJECT_ID); - _asn1_set_name($$,$1);} -; - -imports_def : /* empty */ {$$=NULL;} - | IMPORTS identifier_list FROM IDENTIFIER obj_constant_list - {$$=_asn1_add_node(TYPE_IMPORTS); - _asn1_set_down($$,_asn1_add_node(TYPE_OBJECT_ID)); - _asn1_set_name(_asn1_get_down($$),$4); - _asn1_set_down(_asn1_get_down($$),$5); - _asn1_set_right($$,$2);} -; - -explicit_implicit : EXPLICIT {$$=CONST_EXPLICIT;} - | IMPLICIT {$$=CONST_IMPLICIT;} -; - -definitions: definitions_id - DEFINITIONS explicit_implicit TAGS "::=" BEGIN imports_def - type_constant_list END - {$$=_asn1_add_node(TYPE_DEFINITIONS|$3|(($7==NULL)?0:CONST_IMPORTS)); - _asn1_set_name($$,_asn1_get_name($1)); - _asn1_set_name($1,""); - if($7==NULL) _asn1_set_right($1,$8); - else {_asn1_set_right($7,$8);_asn1_set_right($1,$7);} - _asn1_set_down($$,$1); - if(parse_mode==PARSE_MODE_CREATE){ - _asn1_set_default_tag($$); - _asn1_type_set_config($$); - result_parse=_asn1_check_identifier($$); - if(result_parse==ASN_IDENTIFIER_NOT_FOUND) - asn1_delete_structure($$); - else p_tree=$$; - }} -; - -%% - - -#include <ctype.h> -#include <string.h> - -const char *key_word[]={"::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING" - ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL" - ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER" - ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED" - ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS" - ,"BEGIN","END","UTCTime","GeneralizedTime","FROM" - ,"IMPORTS","NULL","ENUMERATED"}; -const int key_word_token[]={ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING - ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL - ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER - ,BOOLEAN,TRUE,FALSE,APPLICATION,ANY,DEFINED - ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS - ,BEGIN,END,UTCTime,GeneralizedTime,FROM - ,IMPORTS,TOKEN_NULL,ENUMERATED}; - -/*************************************************************/ -/* Function: yylex */ -/* Description: looks for tokens in file_asn1 pointer file. */ -/* Return: int */ -/* Token identifier or ASCII code or 0(zero: End Of File) */ -/*************************************************************/ -int -yylex() -{ - int c,counter=0,k; - char string[129]; /* will contain the next token */ - while(1) - { - while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n'); - if(c==EOF) return 0; - if(c=='(' || c==')' || c=='[' || c==']' || - c=='{' || c=='}' || c==',' || c=='.' || - c=='+') return c; - if(c=='-'){ /* Maybe the first '-' of a comment */ - if((c=fgetc(file_asn1))!='-'){ - ungetc(c,file_asn1); - return '-'; - } - else{ /* Comments */ - counter=0; - /* A comment finishes at the end of line */ - while((c=fgetc(file_asn1))!=EOF && c!='\n'); - if(c==EOF) return 0; - else continue; /* next char, please! (repeat the search) */ - } - } - string[counter++]=c; - /* Till the end of the token */ - while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' || - c=='(' || c==')' || c=='[' || c==']' || - c=='{' || c=='}' || c==',' || c=='.')) - { - string[counter++]=c; - } - ungetc(c,file_asn1); - string[counter]=0; - - /* Is STRING a number? */ - for(k=0;k<counter;k++) - if(!isdigit(string[k])) break; - if(k>=counter) - { - strcpy(yylval.str,string); - return NUM; /* return the number */ - } - - /* Is STRING a keyword? */ - for(k=0;k<(sizeof(key_word)/sizeof(char*));k++) - if(!strcmp(string,key_word[k])) return key_word_token[k]; - - /* STRING is an IDENTIFIER */ - strcpy(yylval.str,string); - return IDENTIFIER; - } -} - - -/** - * asn1_parser_asn1 - function used to start the parse algorithm. - * @file_name: specify the path and the name of file that contains ASN.1 declarations. - * @pointer: return the pointer to the structure created from - * "file_name" ASN.1 declarations. - * Description: - * - * Creates the structures needed to manage the definitions included in *FILE_NAME file. - * - * Returns: - * - * ASN_OK\: the file has a correct syntax and every identifier is known. - * - * ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. - * - * ASN_SYNTAX_ERROR\: the syntax is not correct. - * - * ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. - **/ -int asn1_parser_asn1(char *file_name,node_asn **pointer){ - p_tree=NULL; - *pointer=NULL; - - /* open the file to parse */ - file_asn1=fopen(file_name,"r"); - if(file_asn1==NULL) return ASN_FILE_NOT_FOUND; - - result_parse=ASN_OK; - - /* only syntax check */ - parse_mode=PARSE_MODE_CHECK; - yyparse(); - - if(result_parse==ASN_OK){ /* syntax OK */ - fclose(file_asn1); - file_asn1=fopen(file_name,"r"); - - /* structure creation */ - parse_mode=PARSE_MODE_CREATE; - yyparse(); - - _asn1_change_integer_value(p_tree); - _asn1_expand_object_id(p_tree); - } - - fclose(file_asn1); - - parse_mode=PARSE_MODE_CREATE; - - *pointer=p_tree; - - return result_parse; -} - - -/** - * asn1_parser_asn1_file_c - function that generates a C structure from an ASN1 file - * @file_name: specify the path and the name of file that contains ASN.1 declarations. - * Description: - * - * Creates a file containing a C vector to use to manage the definitions included in - * *FILE_NAME file. If *FILE_NAME is "/aa/bb/xx.yy" the file created is "/aa/bb/xx_asn1_tab.c", - * and the vector is "xx_asn1_tab". - * - * Returns: - * - * ASN_OK\: the file has a correct syntax and every identifier is known. - * - * ASN_FILE_NOT_FOUND\: an error occured while opening FILE_NAME. - * - * ASN_SYNTAX_ERROR\: the syntax is not correct. - * - * ASN_IDENTIFIER_NOT_FOUND\: in the file there is an identifier that is not defined. - **/ -int asn1_parser_asn1_file_c(char *file_name){ - int result; - - p_tree=NULL; - - /* open the file to parse */ - file_asn1=fopen(file_name,"r"); - if(file_asn1==NULL) return ASN_FILE_NOT_FOUND; - - result_parse=ASN_OK; - - /* syntax check */ - parse_mode=PARSE_MODE_CHECK; - yyparse(); - - if(result_parse==ASN_OK){ /* syntax OK */ - fclose(file_asn1); - file_asn1=fopen(file_name,"r"); - - /* structure creation */ - parse_mode=PARSE_MODE_CREATE; - yyparse(); - - /* structure saved in a file */ - result=_asn1_create_static_structure(p_tree,file_name,NULL); - - /* delete structure in memory */ - asn1_delete_structure(p_tree); - } - - fclose(file_asn1); - - parse_mode=PARSE_MODE_CREATE; - - return result_parse; -} - - -/*************************************************************/ -/* Function: yyerror */ -/* Description: function called when there are syntax errors*/ -/* Parameters: */ -/* char *s : error description */ -/* Return: int */ -/* */ -/*************************************************************/ -int yyerror (char *s) -{ - /* Sends the error description to the std_out */ - /* printf("%s\n",s); */ - result_parse=ASN_SYNTAX_ERROR; - return 0; -} - - - - - - - - - - - - - - - diff --git a/lib/Makefile.am b/lib/Makefile.am index b5860cd..47d113c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,18 +1,21 @@ -include_HEADERS = asn1.h +include_HEADERS = libasn1.h -EXTRA_DIST = asn1.h der.h asn1-api.tex mem.h gstr.h +EXTRA_DIST = libasn1.h der.h asn1-api.tex mem.h gstr.h errors.h \ + defines.h int.h parser_aux.h structure.h errors_int.h \ + element.h lib_LTLIBRARIES = libasn1.la # Separate so we can create the documentation -COBJECTS = ASN.y asn1.c der.c gstr.c +COBJECTS = ASN1.y decoding.c gstr.c errors.c parser_aux.c \ + structure.c element.c coding.c libasn1_la_SOURCES = $(COBJECTS) libasn1_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) asn1-api.tex: $(COBJECTS) - @echo "\\newpage" > asn1-api.tex + @echo "% \\newpage" > asn1-api.tex @for i in $(COBJECTS); \ do echo -n "Creating documentation for file $$i... " && ../doc/scripts/gdoc -tex $$i >> asn1-api.tex \ && echo "ok"; \ diff --git a/lib/asn1.c b/lib/asn1.c deleted file mode 100644 index 224922c..0000000 --- a/lib/asn1.c +++ /dev/null @@ -1,1985 +0,0 @@ -/* - * Copyright (C) 2000,2001 Fabio Fiorina - * - * This file is part of GNUTLS. - * - * GNUTLS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUTLS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - - -/*****************************************************/ -/* File: x509_asn1.c */ -/* Description: Functions to manage ASN.1 DEFINITIONS*/ -/*****************************************************/ - - -#include <defines.h> -#include "asn1.h" -#include "der.h" -#include <gstr.h> - -/* define used for visiting trees */ -#define UP 1 -#define RIGHT 2 -#define DOWN 3 - - -int parse_mode; /* PARSE_MODE_CHECK = only syntax check - PARSE_MODE_CREATE = structure creation */ - - -/******************************************************/ -/* Function : _asn1_add_node */ -/* Description: creates a new NODE_ASN element. */ -/* Parameters: */ -/* type: type of the new element (see TYPE_ */ -/* and CONST_ constants). */ -/* Return: pointer to the new element. */ -/******************************************************/ -node_asn * -_asn1_add_node(unsigned int type) -{ - node_asn *punt; - - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - punt=(node_asn *) _asn1_malloc(sizeof(node_asn)); - if (punt==NULL) return NULL; - - punt->left=NULL; - punt->name=NULL; - punt->type=type; - punt->value=NULL; - punt->down=NULL; - punt->right=NULL; - - return punt; -} - -/******************************************************************/ -/* Function : _asn1_set_value */ -/* Description: sets the field VALUE in a NODE_ASN element. The */ -/* previus value (if exist) will be lost */ -/* Parameters: */ -/* node: element pointer. */ -/* value: pointer to the value that you want to set. */ -/* len: character number of value. */ -/* Return: pointer to the NODE_ASN element. */ -/******************************************************************/ -node_asn * -_asn1_set_value(node_asn *node,unsigned char *value,unsigned int len) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return node; - if(node->value){ - _asn1_free(node->value); - node->value=NULL; - } - if(!len) return node; - node->value=(unsigned char *) _asn1_malloc(len); - if (node->value==NULL) return NULL; - - memcpy(node->value,value,len); - return node; -} - -/******************************************************************/ -/* Function : _asn1_set_name */ -/* Description: sets the field NAME in a NODE_ASN element. The */ -/* previus value (if exist) will be lost */ -/* Parameters: */ -/* node: element pointer. */ -/* name: a null terminated string with the name that you want */ -/* to set. */ -/* Return: pointer to the NODE_ASN element. */ -/******************************************************************/ -node_asn * -_asn1_set_name(node_asn *node,char *name) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return node; - - if(node->name){ - _asn1_free(node->name); - node->name=NULL; - } - - if(name==NULL) return node; - - if(strlen(name)) - { - node->name=(char *) _asn1_strdup( name); - if (node->name==NULL) return NULL; - } - else node->name=NULL; - return node; -} - -/******************************************************************/ -/* Function : _asn1_set_right */ -/* Description: sets the field RIGHT in a NODE_ASN element. */ -/* Parameters: */ -/* node: element pointer. */ -/* right: pointer to a NODE_ASN element that you want be pointed*/ -/* by NODE. */ -/* Return: pointer to *NODE. */ -/******************************************************************/ -node_asn * -_asn1_set_right(node_asn *node,node_asn *right) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return node; - node->right=right; - if(right) right->left=node; - return node; -} - -/******************************************************************/ -/* Function : _asn1_get_right */ -/* Description: returns the element pointed by the RIGHT field of */ -/* a NODE_ASN element. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* Return: field RIGHT of NODE. */ -/******************************************************************/ -node_asn * -_asn1_get_right(node_asn *node) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return NULL; - return node->right; -} - -/******************************************************************/ -/* Function : _asn1_get_last_right */ -/* Description: return the last element along the right chain. */ -/* Parameters: */ -/* node: starting element pointer. */ -/* Return: pointer to the last element along the right chain. */ -/******************************************************************/ -node_asn * -_asn1_get_last_right(node_asn *node) -{ - node_asn *p; - - if(parse_mode==PARSE_MODE_CHECK) return NULL; - if(node==NULL) return NULL; - p=node; - while(p->right) p=p->right; - return p; -} - -/******************************************************************/ -/* Function : _asn1_set_down */ -/* Description: sets the field DOWN in a NODE_ASN element. */ -/* Parameters: */ -/* node: element pointer. */ -/* down: pointer to a NODE_ASN element that you want be pointed */ -/* by NODE. */ -/* Return: pointer to *NODE. */ -/******************************************************************/ -node_asn * -_asn1_set_down(node_asn *node,node_asn *down) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return node; - node->down=down; - if(down) down->left=node; - return node; -} - -/******************************************************************/ -/* Function : _asn1_get_down */ -/* Description: returns the element pointed by the DOWN field of */ -/* a NODE_ASN element. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* Return: field DOWN of NODE. */ -/******************************************************************/ -node_asn * -_asn1_get_down(node_asn *node) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return NULL; - return node->down; -} - -/******************************************************************/ -/* Function : _asn1_get_name */ -/* Description: returns the name of a NODE_ASN element. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* Return: a null terminated string. */ -/******************************************************************/ -char * -_asn1_get_name(node_asn *node) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return NULL; - return node->name; -} - -/******************************************************************/ -/* Function : _asn1_mod_type */ -/* Description: change the field TYPE of an NODE_ASN element. */ -/* The new value is the old one | (bitwise or) the */ -/* paramener VALUE. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* value: the integer value that must be or-ed with the current */ -/* value of field TYPE. */ -/* Return: NODE pointer. */ -/******************************************************************/ -node_asn * -_asn1_mod_type(node_asn *node,unsigned int value) -{ - if(parse_mode==PARSE_MODE_CHECK) return NULL; - - if(node==NULL) return node; - node->type|=value; - return node; -} - -/******************************************************************/ -/* Function : _asn1_remove_node */ -/* Description: gets free the memory allocated for an NODE_ASN */ -/* element (not the elements pointed by it). */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/******************************************************************/ -void -_asn1_remove_node(node_asn *node) -{ - if(node==NULL) return; - - if (node->name!=NULL) - _asn1_free(node->name); - if (node->value!=NULL) - _asn1_free(node->value); - _asn1_free(node); -} - - -/******************************************************************/ -/* Function : _asn1_find_mode */ -/* Description: searches an element called NAME starting from */ -/* POINTER. The name is composed by differents */ -/* identifiers separated by dot.The first identifier */ -/* must be the name of *POINTER. */ -/* Parameters: */ -/* pointer: NODE_ASN element pointer. */ -/* name: null terminated string with the element's name to find.*/ -/* Return: the searching result. NULL if not find. */ -/******************************************************************/ -node_asn * -_asn1_find_node(node_asn *pointer,char *name) -{ - node_asn *p; - char *n_start,*n_end,n[128]; - - if((name==NULL) || (name[0]==0)) return NULL; - - n_start=name; - n_end=strchr(n_start,'.'); /* search the first dot */ - if(n_end){ - memcpy(n,n_start,n_end-n_start); - n[n_end-n_start]=0; - n_start=n_end; - n_start++; - } - else{ - _asn1_str_cpy(n,sizeof(n),n_start); - n_start=NULL; - } - - p=pointer; - while(p){ - if((p->name) && (!strcmp(p->name,n))) break; - else p=p->right; - } /* while */ - - if(p==NULL) return NULL; - - while(n_start){ /* Has the end of NAME been reached? */ - n_end=strchr(n_start,'.'); /* search the next dot */ - if(n_end){ - memcpy(n,n_start,n_end-n_start); - n[n_end-n_start]=0; - n_start=n_end; - n_start++; - } - else{ - _asn1_str_cpy(n,sizeof(n),n_start); - n_start=NULL; - } - - if(p->down==NULL) return NULL; - - p=p->down; - - /* The identifier "?LAST" indicates the last element - in the right chain. */ - if(!strcmp(n,"?LAST")){ - if(p==NULL) return NULL; - while(p->right) p=p->right; - } - else{ /* no "?LAST" */ - while(p){ - if((p->name) && (!strcmp(p->name,n))) break; - else p=p->right; - } - if(p==NULL) return NULL; - } - } /* while */ - - return p; -} - -/******************************************************************/ -/* Function : _asn1_find_left */ -/* Description: returns the NODE_ASN element with RIGHT field that*/ -/* points the element NODE. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* Return: NULL if not found. */ -/******************************************************************/ -node_asn * -_asn1_find_left(node_asn *node) -{ - if((node==NULL) || (node->left==NULL) || - (node->left->down==node)) return NULL; - - return node->left; -} - -/******************************************************************/ -/* Function : _asn1_find_up */ -/* Description: return the father of the NODE_ASN element. */ -/* Parameters: */ -/* node: NODE_ASN element pointer. */ -/* Return: Null if not found. */ -/******************************************************************/ -node_asn * -_asn1_find_up(node_asn *node) -{ - node_asn *p; - - if(node==NULL) return NULL; - - p=node; - - while((p->left!=NULL) && (p->left->right==p)) p=p->left; - - return p->left; -} - -/******************************************************************/ -/* Function : _asn1_convert_integer */ -/* Description: converts an integer from a null terminated string */ -/* to der decoding. The convertion from a null */ -/* terminated string to an integer is made with */ -/* the 'strtol' function. */ -/* Parameters: */ -/* value: null terminated string to convert. */ -/* value_out: convertion result (memory must be already */ -/* allocated). */ -/* value_out_size: number of bytes of value_out. */ -/* len: number of significant byte of value_out. */ -/* Return: ASN_MEM_ERROR or ASN_OK */ -/******************************************************************/ -int -_asn1_convert_integer(char *value,unsigned char *value_out,int value_out_size, int *len) -{ - char negative; - unsigned char val[4],temp; - int k,k2; - - *((long*)val)=strtol(value,NULL,10); - for(k=0;k<2;k++){ - temp=val[k]; - val[k]=val[3-k]; - val[3-k]=temp; - } - - if(val[0]&0x80) negative=1; - else negative=0; - - for(k=0;k<3;k++){ - if(negative && (val[k]!=0xFF)) break; - else if(!negative && val[k]) break; - } - - if((negative && !(val[k]&0x80)) || - (!negative && (val[k]&0x80))) k--; - - for(k2=k;k2<4;k2++) { - if (k2-k > value_out_size-1) { - return ASN_MEM_ERROR; - } - /* VALUE_OUT is too short to contain the value convertion */ - value_out[k2-k]=val[k2]; - } - *len=4-k; - - return ASN_OK; -} - -/** - * asn1_create_tree - Creates the structures needed to manage the ASN1 definitions. - * @root: specify vector that contains ASN.1 declarations - * @pointer: return the pointer to the structure created by *ROOT ASN.1 declarations - * Description: - * - * Creates the structures needed to manage the ASN1 definitions. ROOT is a vector created by - * 'asn1_parser_asn1_file_c' function. - * - * Returns: - * - * ASN_OK\: structure created correctly. - * - * ASN_GENERIC_ERROR\: an error occured while structure creation - **/ -int -asn1_create_tree(const static_asn *root,node_asn **pointer) -{ - node_asn *p,*p_last=NULL; - unsigned long k; - int move; - - *pointer=NULL; - move=UP; - - k=0; - while(root[k].value || root[k].type || root[k].name){ - p=_asn1_add_node(root[k].type&(~CONST_DOWN)); - if(root[k].name) _asn1_set_name(p,root[k].name); - if(root[k].value) _asn1_set_value(p,root[k].value,strlen(root[k].value)+1); - - if(*pointer==NULL) *pointer=p; - - if(move==DOWN) _asn1_set_down(p_last,p); - else if(move==RIGHT) _asn1_set_right(p_last,p); - - p_last=p; - - if(root[k].type&CONST_DOWN) move=DOWN; - else if(root[k].type&CONST_RIGHT) move=RIGHT; - else{ - while(1){ - if(p_last==*pointer) break; - - p_last= _asn1_find_up(p_last); - - if(p_last==NULL) break; - - if(p_last->type&CONST_RIGHT){ - p_last->type&=~CONST_RIGHT; - move=RIGHT; - break; - } - } /* while */ - } - k++; - } /* while */ - - if(p_last==*pointer){ - _asn1_change_integer_value(*pointer); - _asn1_expand_object_id(*pointer); - } - else asn1_delete_structure(*pointer); - - return (p_last==*pointer)?ASN_OK:ASN_GENERIC_ERROR; -} - - -int -_asn1_create_static_structure(node_asn *pointer,char *file_name, char* out_name) -{ - FILE *file; - node_asn *p; - unsigned long t; - char structure_name[128],file_out_name[128],*char_p,*slash_p,*dot_p; - - char_p=file_name; - slash_p=file_name; - while((char_p=strchr(char_p,'/'))){ - char_p++; - slash_p=char_p; - } - - char_p=slash_p; - dot_p=file_name+strlen(file_name); - - while((char_p=strchr(char_p,'.'))){ - dot_p=char_p; - char_p++; - } - - memcpy(structure_name,slash_p,dot_p-slash_p); - structure_name[dot_p-slash_p]=0; - _asn1_str_cat(structure_name, sizeof(structure_name),"_asn1_tab"); - - if (out_name==NULL) { - memcpy(file_out_name,file_name,dot_p-file_name); - file_out_name[dot_p-file_name]=0; - _asn1_str_cat(file_out_name, sizeof(file_out_name), "_asn1_tab.c"); - } else { - _asn1_str_cpy( file_out_name, sizeof(file_out_name), out_name); - } - file=fopen( file_out_name,"w"); - - if(file==NULL) return ASN_FILE_NOT_FOUND; - - fprintf(file,"\n#include \"asn1.h\"\n\n"); - fprintf(file,"const static_asn %s[]={\n",structure_name); - - p=pointer; - - while(p){ - fprintf(file," {"); - - if(p->name) fprintf(file,"\"%s\",",p->name); - else fprintf(file,"0,"); - - t=p->type; - if(p->down) t|=CONST_DOWN; - if(p->right) t|=CONST_RIGHT; - - fprintf(file,"%lu,",t); - - if(p->value) fprintf(file,"\"%s\"},\n",p->value); - else fprintf(file,"0},\n"); - - if(p->down){ - p=p->down; - } - else if(p->right){ - p=p->right; - } - else{ - while(1){ - p=_asn1_find_up(p); - if(p==pointer){ - p=NULL; - break; - } - if(p->right){ - p=p->right; - break; - } - } - } - } - - fprintf(file," {0,0,0}\n};\n"); - - fclose(file); - - return ASN_OK; -} - - -/** - * asn1_visit_tree - Prints on the standard output the structure's tree - * @pointer: pointer to the structure that you want to delete. - * @name: an element of the structure - * - * Prints on the standard output the structure's tree starting from the NAME element inside - * the structure *POINTER. - **/ -void -asn1_visit_tree(node_asn *pointer,char *name) -{ - node_asn *p,*root; - int k,indent=0,len,len2,len3; - - root=_asn1_find_node(pointer,name); - - if(root==NULL) return; - - p=root; - while(p){ - for(k=0;k<indent;k++)printf(" "); - - printf("name:"); - if(p->name) printf("%s ",p->name); - else printf("NULL "); - - printf("type:"); - switch(type_field(p->type)){ - case TYPE_NULL: - printf("NULL"); - break; - case TYPE_CONSTANT: - printf("CONST"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_IDENTIFIER: - printf("IDENTIFIER"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_INTEGER: - printf("INTEGER"); - if(p->value){ - len2=-1; - len=_asn1_get_length_der(p->value,&len2); - printf(" value:0x"); - for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]); - } - break; - case TYPE_ENUMERATED: - printf("ENUMERATED"); - if(p->value){ - len2=-1; - len=_asn1_get_length_der(p->value,&len2); - printf(" value:0x"); - for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]); - } - break; - case TYPE_TIME: - printf("TIME"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_BOOLEAN: - printf("BOOLEAN"); - if(p->value){ - if(p->value[0]=='T') printf(" value:TRUE"); - else if(p->value[0]=='F') printf(" value:FALSE"); - } - break; - case TYPE_SEQUENCE: - printf("SEQUENCE"); - break; - case TYPE_BIT_STRING: - printf("BIT_STR"); - if(p->value){ - len2=-1; - len=_asn1_get_length_der(p->value,&len2); - printf(" value(%i):",(len-1)*8-(p->value[len2])); - for(k=1;k<len;k++) printf("%02x",(p->value)[k+len2]); - } - break; - case TYPE_OCTET_STRING: - printf("OCT_STR"); - if(p->value){ - len2=-1; - len=_asn1_get_length_der(p->value,&len2); - printf(" value:"); - for(k=0;k<len;k++) printf("%02x",(p->value)[k+len2]); - } - break; - case TYPE_TAG: - printf("TAG"); - printf(" value:%s",p->value); - break; - case TYPE_DEFAULT: - printf("DEFAULT"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_SIZE: - printf("SIZE"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_SEQUENCE_OF: - printf("SEQ_OF"); - break; - case TYPE_OBJECT_ID: - printf("OBJ_ID"); - if(p->value) printf(" value:%s",p->value); - break; - case TYPE_ANY: - printf("ANY"); - if(p->value){ - len3=-1; - len2=_asn1_get_length_der(p->value,&len3); - printf(" value:"); - for(k=0;k<len2;k++) printf("%02x",(p->value)[k+len3]); - } - - break; - case TYPE_SET: - printf("SET"); - break; - case TYPE_SET_OF: - printf("SET_OF"); - break; - case TYPE_CHOICE: - printf("CHOICE"); - break; - case TYPE_DEFINITIONS: - printf("DEFINITIONS"); - break; - default: - printf("ERROR\n"); - break; - } - - if(p->type&0xFFFFFF00){ - printf(" attr:"); - if(p->type & CONST_UNIVERSAL) printf("UNIVERSAL,"); - if(p->type & CONST_PRIVATE) printf("PRIVATE,"); - if(p->type & CONST_APPLICATION) printf("APPLICATION,"); - if(p->type & CONST_EXPLICIT) printf("EXPLICIT,"); - if(p->type & CONST_IMPLICIT) printf("IMPLICIT,"); - if(p->type & CONST_TAG) printf("TAG,"); - if(p->type & CONST_DEFAULT) printf("DEFAULT,"); - if(p->type & CONST_TRUE) printf("TRUE,"); - if(p->type & CONST_FALSE) printf("FALSE,"); - if(p->type & CONST_LIST) printf("LIST,"); - if(p->type & CONST_MIN_MAX) printf("MIN_MAX,"); - if(p->type & CONST_OPTION) printf("OPTION,"); - if(p->type & CONST_1_PARAM) printf("1_PARAM,"); - if(p->type & CONST_SIZE) printf("SIZE,"); - if(p->type & CONST_DEFINED_BY) printf("DEF_BY,"); - if(p->type & CONST_GENERALIZED) printf("GENERALIZED,"); - if(p->type & CONST_UTC) printf("UTC,"); - if(p->type & CONST_IMPORTS) printf("IMPORTS,"); - if(p->type & CONST_SET) printf("SET,"); - if(p->type & CONST_NOT_USED) printf("NOT_USED,"); - if(p->type & CONST_ASSIGN) printf("ASSIGNEMENT,"); - } - - printf("\n"); - - if(p->down){ - p=p->down; - indent+=2; - } - else if(p==root){ - p=NULL; - break; - } - else if(p->right) p=p->right; - else{ - while(1){ - p=_asn1_find_up(p); - if(p==root){ - p=NULL; - break; - } - indent-=2; - if(p->right){ - p=p->right; - break; - } - } - } - } -} - - -/** - * asn1_delete_structure - Deletes the structure *POINTER. - * @root: pointer to the structure that you want to delete. - * Description: - * - * Deletes the structure *POINTER. - * - * Returns: - * - * ASN_OK\: everything OK - * - * ASN_ELEMENT_NOT_FOUND\: pointer==NULL. - * - **/ -int -asn1_delete_structure(node_asn *root) -{ - node_asn *p,*p2,*p3; - - if(root==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=root; - while(p){ - if(p->down){ - p=p->down; - } - else{ /* no down */ - p2=p->right; - if(p!=root){ - p3=_asn1_find_up(p); - _asn1_set_down(p3,p2); - _asn1_remove_node(p); - p=p3; - } - else{ /* p==root */ - p3=_asn1_find_left(p); - if(!p3){ - p3=_asn1_find_up(p); - if(p3) _asn1_set_down(p3,p2); - else{ - if(p->right) p->right->left=NULL; - } - } - else _asn1_set_right(p3,p2); - _asn1_remove_node(p); - p=NULL; - } - } - } - return ASN_OK; -} - - -node_asn * -_asn1_copy_structure3(node_asn *source_node) -{ - node_asn *dest_node,*p_s,*p_d,*p_d_prev; - int len,len2,move; - - if(source_node==NULL) return NULL; - - dest_node=_asn1_add_node(source_node->type); - - p_s=source_node; - p_d=dest_node; - - move=DOWN; - - do{ - if(move!=UP){ - if(p_s->name) _asn1_set_name(p_d,p_s->name); - if(p_s->value){ - switch(type_field(p_s->type)){ - case TYPE_OCTET_STRING: case TYPE_BIT_STRING: - case TYPE_INTEGER: // case TYPE_DEFAULT: - len2=-1; - len=_asn1_get_length_der(p_s->value,&len2); - _asn1_set_value(p_d,p_s->value,len+len2); - break; - default: - _asn1_set_value(p_d,p_s->value,strlen(p_s->value)+1); - } - } - move=DOWN; - } - else move=RIGHT; - - if(move==DOWN){ - if(p_s->down){ - p_s=p_s->down; - p_d_prev=p_d; - p_d=_asn1_add_node(p_s->type); - _asn1_set_down(p_d_prev,p_d); - } - else move=RIGHT; - } - - if(p_s==source_node) break; - - if(move==RIGHT){ - if(p_s->right){ - p_s=p_s->right; - p_d_prev=p_d; - p_d=_asn1_add_node(p_s->type); - _asn1_set_right(p_d_prev,p_d); - } - else move=UP; - } - if(move==UP){ - p_s=_asn1_find_up(p_s); - p_d=_asn1_find_up(p_d); - } - }while(p_s!=source_node); - - return dest_node; -} - - -node_asn * -_asn1_copy_structure2(node_asn *root,char *source_name) -{ - node_asn *source_node; - - source_node=_asn1_find_node(root,source_name); - - return _asn1_copy_structure3(source_node); - -} - - -/** - * asn1_create_structure - Creates a structure called DEST_NAME of type SOURCE_NAME. - * @root: pointer to the structure returned by "parser_asn1" function - * @source_name: the name of the type of the new structure (must be inside p_structure). - * @pointer: pointer to the structure created. - * @dest_name: the name of the new structure. - * Description: - * - * Creates a structure called DEST_NAME of type SOURCE_NAME. - * - * Returns: - * - * ASN_OK\: creation OK - * - * ASN_ELEMENT_NOT_FOUND\: SOURCE_NAME isn't known - * - * Example: using "pkix.asn" - * result=asn1_create_structure(cert_def,"PKIX1.Certificate",&cert,"certificate1"); - **/ -int -asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer,char *dest_name) -{ - node_asn *dest_node; - int res; - char *end,n[129]; - - *pointer=NULL; - - dest_node=_asn1_copy_structure2(root,source_name); - - if(dest_node==NULL) return ASN_ELEMENT_NOT_FOUND; - - _asn1_set_name(dest_node,dest_name); - - end=strchr(source_name,'.'); - if(end){ - memcpy(n,source_name,end-source_name); - n[end-source_name]=0; - } - else{ - _asn1_str_cpy(n,sizeof(n),source_name); - } - - res=_asn1_expand_identifier(&dest_node,root); - _asn1_type_choice_config(dest_node); - - *pointer=dest_node; - - return res; -} - - -int -_asn1_append_sequence_set(node_asn *node) -{ - node_asn *p,*p2; - char temp[10]; - long n; - - if(!node || !(node->down)) return ASN_GENERIC_ERROR; - - p=node->down; - while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right; - p2=_asn1_copy_structure3(p); - while(p->right) p=p->right; - _asn1_set_right(p,p2); - - if(p->name==NULL) _asn1_str_cpy(temp,sizeof(temp),"?1"); - else{ - n=strtol(p->name+1,NULL,0); - n++; - temp[0]='?'; - _asn1_ltostr(n,temp+1); - } - _asn1_set_name(p2,temp); - - return ASN_OK; -} - - -/** - * asn1_write_value - Set the value of one element inside a structure. - * @node_root: pointer to a structure - * @name: the name of the element inside the structure that you want to set. - * @value: vector used to specify the value to set. If len is >0, - * VALUE must be a two's complement form integer. - * if len=0 *VALUE must be a null terminated string with an integer value. - * @len: number of bytes of *value to use to set the value: value[0]..value[len-1] - * or 0 if value is a null terminated string - * Description: - * - * Set the value of one element inside a structure. - * - * Returns: - * - * ASN_OK\: set value OK - * - * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element. - * - * ASN_VALUE_NOT_VALID\: VALUE has a wrong format. - * - * Examples: - * description for each type - * - *\begin{itemize} - * \item INTEGER\: VALUE must contain a two's complement form integer. - * value[0]=0xFF , len=1 -> integer=-1 - * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1 - * value[0]=0x01 , len=1 -> integer= 1 - * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1 - * value="123" , len=0 -> integer= 123 - * - * \item ENUMERATED\: as INTEGER (but only with not negative numbers) - * - * \item BOOLEAN\: VALUE must be the null terminated string "TRUE" or "FALSE" and LEN != 0 - * value="TRUE" , len=1 -> boolean=TRUE - * value="FALSE" , len=1 -> boolean=FALSE - * - * \item OBJECT IDENTIFIER\: VALUE must be a null terminated string with each number separated by - * a blank (e.g. "1 2 3 543 1"). - * LEN != 0 - * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha - * - * \item UTCTime\: VALUE must be a null terminated string in one of these formats\: - * "YYMMDDhhmmssZ" "YYMMDDhhmmssZ" "YYMMDDhhmmss+hh'mm'" "YYMMDDhhmmss-hh'mm'" - * "YYMMDDhhmm+hh'mm'" "YYMMDDhhmm-hh'mm'". - * LEN != 0 - * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 at 12h 00m Greenwich Mean Time - * - * \item GeneralizedTime\: VALUE must be in one of this format\: - * "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.sZ" "YYYYMMDDhhmmss.s+hh'mm'" - * "YYYYMMDDhhmmss.s-hh'mm'" "YYYYMMDDhhmm+hh'mm'" "YYYYMMDDhhmm-hh'mm'" - * where ss.s indicates the seconds with any precision like "10.1" or "01.02". - * LEN != 0 - * value="2001010112001.12-0700" , len=1 -> time=Jannuary 1st, 2001 at 12h 00m 01.12s - * Pacific Daylight Time - * - * \item OCTET STRING\: VALUE contains the octet string and LEN is the number of octet. - * value="$\backslash$x01$\backslash$x02$\backslash$x03" , len=3 -> three bytes octet string - * - * \item BIT STRING\: VALUE contains the bit string organized by bytes and LEN is the number of bits. - * value="$\backslash$xCF" , len=6 -> bit string="110011" (six bits) - * - * \item CHOICE\: if NAME indicates a choice type, VALUE must specify one of the alternatives with a - * null terminated string. LEN != 0 - * Using "pkix.asn"\: - * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject","rdnSequence",1); - * - * \item ANY\: VALUE indicates the der encoding of a structure. - * LEN != 0 - * - * \item SEQUENCE OF\: VALUE must be the null terminated string "NEW" and LEN != 0. With this - * instruction another element is appended in the sequence. The name of this - * element will be "?1" if it's the first one, "?2" for the second and so on. - * - * Using "pkix.asn"\: - * - * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence","NEW",1); - * - * \item SET OF\: the same as SEQUENCE OF. - * Using "pkix.asn": - * - * result=asn1_write_value(cert,"certificate1.tbsCertificate.subject.rdnSequence.?LAST","NEW",1); - *\end{itemize} - * - * If an element is OPTIONAL and you want to delete it, you must use the value=NULL and len=0. - * - * Using "pkix.asn"\: - * - * result=asn1_write_value(cert,"certificate1.tbsCertificate.issuerUniqueID",NULL,0); - * - **/ -int -asn1_write_value(node_asn *node_root,char *name,unsigned char *value,int len) -{ - node_asn *node,*p,*p2; - unsigned char *temp,*value_temp=NULL,*default_temp=NULL; - int len2,k,k2,negative; - - node=_asn1_find_node(node_root,name); - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - if((node->type & CONST_OPTION) && (value==NULL) && (len==0)){ - asn1_delete_structure(node); - return ASN_OK; - } - - switch(type_field(node->type)){ - case TYPE_BOOLEAN: - if(!strcmp(value,"TRUE")){ - if(node->type&CONST_DEFAULT){ - p=node->down; - while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if(p->type&CONST_TRUE) _asn1_set_value(node,NULL,0); - else _asn1_set_value(node,"T",1); - } - else _asn1_set_value(node,"T",1); - } - else if(!strcmp(value,"FALSE")){ - if(node->type&CONST_DEFAULT){ - p=node->down; - while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if(p->type&CONST_FALSE) _asn1_set_value(node,NULL,0); - else _asn1_set_value(node,"F",1); - } - else _asn1_set_value(node,"F",1); - } - else return ASN_VALUE_NOT_VALID; - break; - case TYPE_INTEGER: case TYPE_ENUMERATED: - if(len==0){ - if(isdigit(value[0])){ - value_temp=(unsigned char *)_asn1_alloca(4); - if (value_temp==NULL) return ASN_MEM_ERROR; - - _asn1_convert_integer(value,value_temp,4, &len); - } - else{ /* is an identifier like v1 */ - if(!(node->type&CONST_LIST)) return ASN_VALUE_NOT_VALID; - p=node->down; - while(p){ - if(type_field(p->type)==TYPE_CONSTANT){ - if((p->name) && (!strcmp(p->name,value))){ - value_temp=(unsigned char *)_asn1_alloca(4); - if (value_temp==NULL) return ASN_MEM_ERROR; - - _asn1_convert_integer(p->value,value_temp,4, &len); - break; - } - } - p=p->right; - } - if(p==NULL) return ASN_VALUE_NOT_VALID; - } - } - else{ - value_temp=(unsigned char *)_asn1_alloca(len); - if (value_temp==NULL) return ASN_MEM_ERROR; - memcpy(value_temp,value,len); - } - - - if(value_temp[0]&0x80) negative=1; - else negative=0; - - if(negative && (type_field(node->type)==TYPE_ENUMERATED)) - {_asn1_afree(value_temp);return ASN_VALUE_NOT_VALID;} - - for(k=0;k<len-1;k++) - if(negative && (value_temp[k]!=0xFF)) break; - else if(!negative && value_temp[k]) break; - - if((negative && !(value_temp[k]&0x80)) || - (!negative && (value_temp[k]&0x80))) k--; - - _asn1_length_der(len-k,NULL,&len2); - temp=(unsigned char *)_asn1_alloca(len-k+len2); - if (temp==NULL) return ASN_MEM_ERROR; - - _asn1_octet_der(value_temp+k,len-k,temp,&len2); - _asn1_set_value(node,temp,len2); - - _asn1_afree(temp); - - if(node->type&CONST_DEFAULT){ - p=node->down; - while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if(isdigit(p->value[0])){ - default_temp=(unsigned char *)_asn1_alloca(4); - if (default_temp==NULL) return ASN_MEM_ERROR; - - _asn1_convert_integer(p->value,default_temp,4,&len2); - } - else{ /* is an identifier like v1 */ - if(!(node->type&CONST_LIST)) return ASN_VALUE_NOT_VALID; - p2=node->down; - while(p2){ - if(type_field(p2->type)==TYPE_CONSTANT){ - if((p2->name) && (!strcmp(p2->name,p->value))){ - default_temp=(unsigned char *)_asn1_alloca(4); - if (default_temp==NULL) return ASN_MEM_ERROR; - - _asn1_convert_integer(p2->value,default_temp,4,&len2); - break; - } - } - p2=p2->right; - } - if(p2==NULL) return ASN_VALUE_NOT_VALID; - } - - if((len-k)==len2){ - for(k2=0;k2<len2;k2++) - if(value_temp[k+k2]!=default_temp[k2]){ - break; - } - if(k2==len2) _asn1_set_value(node,NULL,0); - } - _asn1_afree(default_temp); - } - _asn1_afree(value_temp); - break; - case TYPE_OBJECT_ID: - for(k=0;k<strlen(value);k++) - if((!isdigit(value[k])) && (value[k]!=' ') && (value[k]!='+')) - return ASN_VALUE_NOT_VALID; - _asn1_set_value(node,value,strlen(value)+1); - break; - case TYPE_TIME: - if(node->type&CONST_UTC){ - if(strlen(value)<11) return ASN_VALUE_NOT_VALID; - for(k=0;k<10;k++) - if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID; - switch(strlen(value)){ - case 11: - if(value[10]!='Z') return ASN_VALUE_NOT_VALID; - break; - case 13: - if((!isdigit(value[10])) || (!isdigit(value[11])) || - (value[12]!='Z')) return ASN_VALUE_NOT_VALID; - break; - case 15: - if((value[10]!='+') && (value[10]!='-')) return ASN_VALUE_NOT_VALID; - for(k=11;k<15;k++) - if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID; - break; - case 17: - if((!isdigit(value[10])) || (!isdigit(value[11]))) - return ASN_VALUE_NOT_VALID; - if((value[12]!='+') && (value[12]!='-')) return ASN_VALUE_NOT_VALID; - for(k=13;k<17;k++) - if(!isdigit(value[k])) return ASN_VALUE_NOT_VALID; - break; - default: - return ASN_VALUE_NOT_FOUND; - } - _asn1_set_value(node,value,strlen(value)+1); - } - else{ /* GENERALIZED TIME */ - if(value) _asn1_set_value(node,value,strlen(value)+1); - } - break; - case TYPE_OCTET_STRING: - _asn1_length_der(len,NULL,&len2); - temp=(unsigned char *)_asn1_alloca(len+len2); - if (temp==NULL) return ASN_MEM_ERROR; - - _asn1_octet_der(value,len,temp,&len2); - _asn1_set_value(node,temp,len2); - _asn1_afree(temp); - break; - case TYPE_BIT_STRING: - _asn1_length_der((len>>3)+2,NULL,&len2); - temp=(unsigned char *)_asn1_alloca((len>>3)+2+len2); - if (temp==NULL) return ASN_MEM_ERROR; - - _asn1_bit_der(value,len,temp,&len2); - _asn1_set_value(node,temp,len2); - _asn1_afree(temp); - break; - case TYPE_CHOICE: - p=node->down; - while(p){ - if(!strcmp(p->name,value)){ - p2=node->down; - while(p2){ - if(p2!=p){asn1_delete_structure(p2); p2=node->down;} - else p2=p2->right; - } - break; - } - p=p->right; - } - if(!p) return ASN_ELEMENT_NOT_FOUND; - break; - case TYPE_ANY: - _asn1_length_der(len,NULL,&len2); - temp=(unsigned char *)_asn1_alloca(len+len2); - if (temp==NULL) return ASN_MEM_ERROR; - - _asn1_octet_der(value,len,temp,&len2); - _asn1_set_value(node,temp,len2); - _asn1_afree(temp); - break; - case TYPE_SEQUENCE_OF: case TYPE_SET_OF: - if(strcmp(value,"NEW")) return ASN_VALUE_NOT_VALID; - _asn1_append_sequence_set(node); - break; - default: - return ASN_ELEMENT_NOT_FOUND; - break; - } - - return ASN_OK; -} - -#define PUT_VALUE( ptr, ptr_size, data, data_size) \ - *len = data_size; \ - if (ptr_size < data_size) { \ - return ASN_MEM_ERROR; \ - } else { \ - memcpy( ptr, data, data_size); \ - } - -#define PUT_STR_VALUE( ptr, ptr_size, data) \ - *len = strlen(data) + 1; \ - if (ptr_size < *len) { \ - return ASN_MEM_ERROR; \ - } else { \ - /* this strcpy is checked */ \ - strcpy(ptr, data); \ - } - -#define ADD_STR_VALUE( ptr, ptr_size, data) \ - *len = strlen(data) + 1; \ - if (ptr_size < strlen(ptr)+(*len)) { \ - return ASN_MEM_ERROR; \ - } else { \ - /* this strcat is checked */ \ - strcat(ptr, data); \ - } - -/** - * asn1_read_value - Returns the value of one element inside a structure - * @root: pointer to a structure - * @name: the name of the element inside a structure that you want to read. - * @value: vector that will contain the element's content. - * VALUE must be a pointer to memory cells already allocated. - * @len: number of bytes of *value: value[0]..value[len-1]. Initialy holds the sizeof value. - * - * Description: - * - * Returns the value of one element inside a structure. - * - * Returns: - * - * ASN_OK\: set value OK - * - * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element. - * - * ASN_VALUE_NOT_FOUND\: there isn't any value for the element selected. - * - * Examples: - * a description for each type - * - *\begin{itemize} - * \item INTEGER\: VALUE will contain a two's complement form integer. - * integer=-1 -> value[0]=0xFF , len=1 - * integer=1 -> value[0]=0x01 , len=1 - * - * \item ENUMERATED\: as INTEGER (but only with not negative numbers) - * - * \item BOOLEAN\: VALUE will be the null terminated string "TRUE" or "FALSE" and LEN=5 or LEN=6 - * - * \item OBJECT IDENTIFIER\: VALUE will be a null terminated string with each number separated by - * a blank (i.e. "1 2 3 543 1"). - * LEN = strlen(VALUE)+1 - * - * \item UTCTime\: VALUE will be a null terminated string in one of these formats\: - * "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'" - * LEN=strlen(VALUE)+1 - * - * \item GeneralizedTime\: VALUE will be a null terminated string in the same format used to set - * the value - * - * \item OCTET STRING\: VALUE will contain the octet string and LEN will be the number of octet. - * - * \item BIT STRING\: VALUE will contain the bit string organized by bytes and LEN will be the - * number of bits. - * - * \item CHOICE\: if NAME indicates a choice type, VALUE will specify the alternative selected - * - * \item ANY\: if NAME indicates an any type, VALUE will indicate the DER encoding of the structure - * actually used. - *\end{itemize} - * - * If an element is OPTIONAL and the function "read_value" returns ASN_ELEMENT_NOT_FOUND, it - * means that this element wasn't present in the der encoding that created the structure. - * The first element of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and so on. - * - **/ -int -asn1_read_value(node_asn *root,char *name,unsigned char *value, int *len) -{ - node_asn *node,*p; - int len2,len3; - int value_size = *len; - - node=_asn1_find_node(root,name); - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - if((type_field(node->type)!=TYPE_NULL) && - (type_field(node->type)!=TYPE_CHOICE) && - !(node->type&CONST_DEFAULT) && !(node->type&CONST_ASSIGN) && - (node->value==NULL)) - return ASN_VALUE_NOT_FOUND; - - switch(type_field(node->type)){ - case TYPE_NULL: - PUT_STR_VALUE( value, value_size, "NULL"); - break; - case TYPE_BOOLEAN: - if((node->type&CONST_DEFAULT) && (node->value==NULL)){ - p=node->down; - while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if(p->type&CONST_TRUE) { - PUT_STR_VALUE( value, value_size, "TRUE"); - } else { - PUT_STR_VALUE(value, value_size, "FALSE"); - } - } - else if(node->value[0]=='T') { - PUT_STR_VALUE(value, value_size, "TRUE"); - } - else { - PUT_STR_VALUE(value, value_size, "FALSE"); - } - break; - case TYPE_INTEGER: case TYPE_ENUMERATED: - if((node->type&CONST_DEFAULT) && (node->value==NULL)){ - p=node->down; - while(type_field(p->type)!=TYPE_DEFAULT) p=p->right; - if (_asn1_convert_integer(p->value,value,value_size, len)!=ASN_OK) return ASN_MEM_ERROR; - } - else{ - len2=-1; - if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN_OK) return ASN_MEM_ERROR; - } - break; - case TYPE_OBJECT_ID: - if(node->type&CONST_ASSIGN){ - _asn1_str_cpy(value, *len, ""); - p=node->down; - while(p){ - if(type_field(p->type)==TYPE_CONSTANT){ - ADD_STR_VALUE( value, value_size, p->value); - if(p->right) { - ADD_STR_VALUE( value, value_size, " "); - } - } - p=p->right; - } - } else { - PUT_STR_VALUE(value, value_size, node->value); - } - break; - case TYPE_TIME: - PUT_STR_VALUE( value, value_size, node->value); - break; - case TYPE_OCTET_STRING: - len2=-1; - if (_asn1_get_octet_der(node->value,&len2,value, value_size, len)!=ASN_OK) return ASN_MEM_ERROR; - break; - case TYPE_BIT_STRING: - len2=-1; - if (_asn1_get_bit_der(node->value,&len2,value,value_size,len)!=ASN_OK) return ASN_MEM_ERROR; - break; - case TYPE_CHOICE: - PUT_STR_VALUE( value, value_size, node->down->name); - break; - case TYPE_ANY: - len3=-1; - len2=_asn1_get_length_der(node->value,&len3); - PUT_VALUE( value, value_size, node->value+len3, len2); - break; - default: - return ASN_ELEMENT_NOT_FOUND; - break; - } - return ASN_OK; -} - -/** - * asn1_number_of_elements - Counts the number of elements of a structure. - * @root: pointer to the root of an ASN1 structure. - * @name: the name of a sub-structure of ROOT. - * @num: pointer to an integer where the result will be stored - * Description: - * - * Counts the number of elements of a sub-structure called NAME with names equal to "?1","?2", ... - * - * Returns: - * - * ASN_OK: creation OK - * ASN_ELEMENT_NOT_FOUND: NAME isn't known - * ASN_GENERIC_ERROR: parameter num equal to NULL - * - **/ -int -asn1_number_of_elements(node_asn *root,char *name,int *num) -{ - node_asn *node,*p; - - if(num==NULL) return ASN_GENERIC_ERROR; - - *num=0; - - node=_asn1_find_node(root,name); - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node->down; - - while(p){ - if((p->name) && (p->name[0]=='?')) (*num)++; - p=p->right; - } - - return ASN_OK; -} - - -int -_asn1_set_default_tag(node_asn *node) -{ - node_asn *p; - - if((node==NULL) || (type_field(node->type)!=TYPE_DEFINITIONS)) - return ASN_ELEMENT_NOT_FOUND; - - p=node; - while(p){ - if((type_field(p->type)==TYPE_TAG) && - !(p->type&CONST_EXPLICIT) && - !(p->type&CONST_IMPLICIT)){ - if(node->type&CONST_EXPLICIT) p->type|=CONST_EXPLICIT; - else p->type|=CONST_IMPLICIT; - } - - if(p->down){ - p=p->down; - } - else if(p->right) p=p->right; - else{ - while(1){ - p=_asn1_find_up(p); - if(p==node){ - p=NULL; - break; - } - if(p->right){ - p=p->right; - break; - } - } - } - } - - return ASN_OK; -} - - -int -_asn1_check_identifier(node_asn *node) -{ - node_asn *p,*p2; - char name2[129]; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node; - while(p){ - if(type_field(p->type)==TYPE_IDENTIFIER){ - _asn1_str_cpy(name2, sizeof(name2), node->name); - _asn1_str_cat(name2, sizeof(name2), "."); - _asn1_str_cat(name2, sizeof(name2), p->value); - p2=_asn1_find_node(node,name2); - if(p2==NULL){printf("%s\n",name2); return ASN_IDENTIFIER_NOT_FOUND;} - } - else if((type_field(p->type)==TYPE_OBJECT_ID) && - (p->type&CONST_ASSIGN)){ - p2=p->down; - if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ - if(p2->value && !isdigit(p2->value[0])){ - _asn1_str_cpy(name2, sizeof(name2), node->name); - _asn1_str_cat(name2, sizeof(name2), "."); - _asn1_str_cat(name2, sizeof(name2), p2->value); - p2=_asn1_find_node(node,name2); - if(!p2 || (type_field(p2->type)!=TYPE_OBJECT_ID) || - !(p2->type&CONST_ASSIGN)) - {printf("%s\n",name2); return ASN_IDENTIFIER_NOT_FOUND;} - } - } - } - - if(p->down){ - p=p->down; - } - else if(p->right) p=p->right; - else{ - while(1){ - p=_asn1_find_up(p); - if(p==node){ - p=NULL; - break; - } - if(p->right){ - p=p->right; - break; - } - } - } - } - - return ASN_OK; -} - - -int -_asn1_change_integer_value(node_asn *node) -{ - node_asn *p; - unsigned char val[4],val2[5]; - int len; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node; - while(p){ - if((type_field(p->type)==TYPE_INTEGER) && (p->type&CONST_ASSIGN)){ - if(p->value){ - _asn1_convert_integer(p->value,val,sizeof(val), &len); - _asn1_octet_der(val,len,val2,&len); - _asn1_set_value(p,val2,len); - } - } - - if(p->down){ - p=p->down; - } - else{ - if(p==node) p=NULL; - else if(p->right) p=p->right; - else{ - while(1){ - p=_asn1_find_up(p); - if(p==node){ - p=NULL; - break; - } - if(p->right){ - p=p->right; - break; - } - } - } - } - } - - return ASN_OK; -} - - -int -_asn1_delete_not_used(node_asn *node) -{ - node_asn *p,*p2; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node; - while(p){ - if(p->type&CONST_NOT_USED){ - p2=NULL; - if(p!=node){ - p2=_asn1_find_left(p); - if(!p2) p2=_asn1_find_up(p); - } - asn1_delete_structure(p); - p=p2; - } - - if(!p) break; /* reach node */ - - if(p->down){ - p=p->down; - } - else{ - if(p==node) p=NULL; - else if(p->right) p=p->right; - else{ - while(1){ - p=_asn1_find_up(p); - if(p==node){ - p=NULL; - break; - } - if(p->right){ - p=p->right; - break; - } - } - } - } - } - return ASN_OK; -} - - - -int -_asn1_expand_identifier(node_asn **node,node_asn *root) -{ - node_asn *p,*p2,*p3; - char name2[129]; - int move; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=*node; - move=DOWN; - - while(!((p==*node) && (move==UP))){ - if(move!=UP){ - if(type_field(p->type)==TYPE_IDENTIFIER){ - _asn1_str_cpy(name2, sizeof(name2), root->name); - _asn1_str_cat(name2, sizeof(name2), "."); - _asn1_str_cat(name2, sizeof(name2), p->value); - p2=_asn1_copy_structure2(root,name2); - if(p2==NULL) return ASN_IDENTIFIER_NOT_FOUND; - _asn1_set_name(p2,p->name); - p2->right=p->right; - p2->left=p->left; - if(p->right) p->right->left=p2; - p3=p->down; - if(p3){ - while(p3->right) p3=p3->right; - _asn1_set_right(p3,p2->down); - _asn1_set_down(p2,p->down); - } - - p3=_asn1_find_left(p); - if(p3) _asn1_set_right(p3,p2); - else{ - p3=_asn1_find_up(p); - if(p3) _asn1_set_down(p3,p2); - else { - p2->left=NULL; - } - } - - if(p->type & CONST_SIZE) p2->type|=CONST_SIZE; - if(p->type & CONST_TAG) p2->type|=CONST_TAG; - if(p->type & CONST_OPTION) p2->type|=CONST_OPTION; - if(p->type & CONST_DEFAULT) p2->type|=CONST_DEFAULT; - if(p->type & CONST_SET) p2->type|=CONST_SET; - if(p->type & CONST_NOT_USED) p2->type|=CONST_NOT_USED; - - if(p==*node) *node=p2; - _asn1_remove_node(p); - p=p2; - move=DOWN; - continue; - } - move=DOWN; - } - else move=RIGHT; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - - if(p==*node) {move=UP; continue;} - - if(move==RIGHT){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - return ASN_OK; -} - - - -int -_asn1_type_choice_config(node_asn *node) -{ - node_asn *p,*p2,*p3,*p4; - int move; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node; - move=DOWN; - - while(!((p==node) && (move==UP))){ - if(move!=UP){ - if((type_field(p->type)==TYPE_CHOICE) && - (p->type&CONST_TAG)){ - p2=p->down; - while(p2){ - if(type_field(p2->type)!=TYPE_TAG){ - p2->type|=CONST_TAG; - p3=_asn1_find_left(p2); - while(p3){ - if(type_field(p3->type)==TYPE_TAG){ - p4=_asn1_add_node(p3->type); - _asn1_set_value(p4,p3->value,strlen(p3->value)+1); - _asn1_set_right(p4,p2->down); - _asn1_set_down(p2,p4); - } - p3=_asn1_find_left(p3); - } - } - p2=p2->right; - } - p->type&=~(CONST_TAG); - p2=p->down; - while(p2){ - p3=p2->right; - if(type_field(p2->type)==TYPE_TAG) asn1_delete_structure(p2); - p2=p3; - } - } - move=DOWN; - } - else move=RIGHT; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - - if(p==node) {move=UP; continue;} - - if(move==RIGHT){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - return ASN_OK; -} - - -int -_asn1_type_set_config(node_asn *node) -{ - node_asn *p,*p2; - int move; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - p=node; - move=DOWN; - - while(!((p==node) && (move==UP))){ - if(move!=UP){ - if(type_field(p->type)==TYPE_SET){ - p2=p->down; - while(p2){ - if(type_field(p2->type)!=TYPE_TAG) - p2->type|=CONST_SET|CONST_NOT_USED; - p2=p2->right; - } - } - move=DOWN; - } - else move=RIGHT; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - - if(p==node) {move=UP; continue;} - - if(move==RIGHT){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - return ASN_OK; -} - - -int -_asn1_expand_object_id(node_asn *node) -{ - node_asn *p,*p2,*p3,*p4,*p5; - char name_root[129],name2[129]; - int move; - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - _asn1_str_cpy(name_root, sizeof(name_root), node->name); - - p=node; - move=DOWN; - - while(!((p==node) && (move==UP))){ - if(move!=UP){ - if((type_field(p->type)==TYPE_OBJECT_ID) && (p->type&CONST_ASSIGN)){ - p2=p->down; - if(p2 && (type_field(p2->type)==TYPE_CONSTANT)){ - if(p2->value && !isdigit(p2->value[0])){ - _asn1_str_cpy(name2, sizeof(name2), name_root); - _asn1_str_cat(name2, sizeof(name2), "."); - _asn1_str_cat(name2, sizeof(name2), p2->value); - p3=_asn1_find_node(node,name2); - if(!p3 || (type_field(p3->type)!=TYPE_OBJECT_ID) || - !(p3->type&CONST_ASSIGN)) return ASN_ELEMENT_NOT_FOUND; - _asn1_set_down(p,p2->right); - _asn1_remove_node(p2); - p2=p; - p4=p3->down; - while(p4){ - if(type_field(p4->type)==TYPE_CONSTANT){ - p5=_asn1_add_node(TYPE_CONSTANT); - _asn1_set_name(p5,p4->name); - _asn1_set_value(p5,p4->value,strlen(p4->value)+1); - if(p2==p){ - _asn1_set_right(p5,p->down); - _asn1_set_down(p,p5); - } - else{ - _asn1_set_right(p5,p2->right); - _asn1_set_right(p2,p5); - } - p2=p5; - } - p4=p4->right; - } - move=DOWN; - continue; - } - } - } - move=DOWN; - } - else move=RIGHT; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - - if(p==node) {move=UP; continue;} - - if(move==RIGHT){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - return ASN_OK; -} - - - - - - - - - - - - - diff --git a/lib/asn1.h b/lib/asn1.h deleted file mode 100644 index 2890b9d..0000000 --- a/lib/asn1.h +++ /dev/null @@ -1,204 +0,0 @@ - -/*************************************************/ -/* File: x509_asn1.h */ -/* Description: list of exported object by */ -/* "x509_asn1.c" */ -/*************************************************/ - -#ifndef _GNUTLS_ASN1_H -#define _GNUTLS_ASN1_H - -#define PARSE_MODE_CHECK 1 -#define PARSE_MODE_CREATE 2 - -/* List of constants for field type of typedef node_asn */ -#define TYPE_CONSTANT 1 -#define TYPE_IDENTIFIER 2 -#define TYPE_INTEGER 3 -#define TYPE_BOOLEAN 4 -#define TYPE_SEQUENCE 5 -#define TYPE_BIT_STRING 6 -#define TYPE_OCTET_STRING 7 -#define TYPE_TAG 8 -#define TYPE_DEFAULT 9 -#define TYPE_SIZE 10 -#define TYPE_SEQUENCE_OF 11 -#define TYPE_OBJECT_ID 12 -#define TYPE_ANY 13 -#define TYPE_SET 14 -#define TYPE_SET_OF 15 -#define TYPE_DEFINITIONS 16 -#define TYPE_TIME 17 -#define TYPE_CHOICE 18 -#define TYPE_IMPORTS 19 -#define TYPE_NULL 20 -#define TYPE_ENUMERATED 21 - - -/***********************************************************************/ -/* List of constants for specify better the type of typedef node_asn. */ -/***********************************************************************/ -/* Used with TYPE_TAG */ -#define CONST_UNIVERSAL (1<<8) -#define CONST_PRIVATE (1<<9) -#define CONST_APPLICATION (1<<10) -#define CONST_EXPLICIT (1<<11) -#define CONST_IMPLICIT (1<<12) - -#define CONST_TAG (1<<13) /* Used in ASN.1 assignement */ -#define CONST_OPTION (1<<14) -#define CONST_DEFAULT (1<<15) -#define CONST_TRUE (1<<16) -#define CONST_FALSE (1<<17) - -#define CONST_LIST (1<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ -#define CONST_MIN_MAX (1<<19) - -#define CONST_1_PARAM (1<<20) - -#define CONST_SIZE (1<<21) - -#define CONST_DEFINED_BY (1<<22) - -#define CONST_GENERALIZED (1<<23) -#define CONST_UTC (1<<24) - -#define CONST_IMPORTS (1<<25) - -#define CONST_NOT_USED (1<<26) -#define CONST_SET (1<<27) -#define CONST_ASSIGN (1<<28) - -#define CONST_DOWN (1<<29) -#define CONST_RIGHT (1<<30) - - -#define ASN_OK 0 -#define ASN_FILE_NOT_FOUND 1 -#define ASN_ELEMENT_NOT_FOUND 2 -#define ASN_IDENTIFIER_NOT_FOUND 3 -#define ASN_DER_ERROR 4 -#define ASN_VALUE_NOT_FOUND 5 -#define ASN_GENERIC_ERROR 6 -#define ASN_VALUE_NOT_VALID 7 -#define ASN_TAG_ERROR 8 -#define ASN_TAG_IMPLICIT 9 -#define ASN_ERROR_TYPE_ANY 10 -#define ASN_SYNTAX_ERROR 11 -#define ASN_MEM_ERROR 12 -#define ASN_DER_OVERFLOW 13 - - -/******************************************************/ -/* Structure definition used for the node of the tree */ -/* that rappresent an ASN.1 DEFINITION. */ -/******************************************************/ -typedef struct node_asn_struct{ - char *name; /* Node name */ - unsigned int type; /* Node type */ - unsigned char *value; /* Node value */ - struct node_asn_struct *down; /* Pointer to the son node */ - struct node_asn_struct *right; /* Pointer to the brother node */ - struct node_asn_struct *left; /* Pointer to the next list element */ -} node_asn; - - - -typedef struct static_struct_asn{ - char *name; /* Node name */ - unsigned int type; /* Node type */ - unsigned char *value; /* Node value */ -} static_asn; - - -/****************************************/ -/* Returns the first 8 bits. */ -/* Used with the field type of node_asn */ -/****************************************/ -#define type_field(x) (x&0xFF) - - -/***************************************/ -/* Functions used by ASN.1 parser */ -/***************************************/ -node_asn * -_asn1_add_node(unsigned int type); - -node_asn * -_asn1_set_value(node_asn *node,unsigned char *value,unsigned int len); - -node_asn * -_asn1_set_name(node_asn *node,char *name); - -node_asn * -_asn1_set_right(node_asn *node,node_asn *right); - -node_asn * -_asn1_get_right(node_asn *node); - -node_asn * -_asn1_get_last_right(node_asn *node); - -node_asn * -_asn1_set_down(node_asn *node,node_asn *down); - -char * -_asn1_get_name(node_asn *node); - -node_asn * -_asn1_get_down(node_asn *node); - -node_asn * -_asn1_mod_type(node_asn *node,unsigned int value); - -void -_asn1_append_tree(node_asn *node); - -node_asn * -_asn1_find_node(node_asn *pointer,char *name); - -node_asn * -_asn1_find_up(node_asn *node); - -int -_asn1_append_sequence_set(node_asn *node); - -int -_asn1_delete_not_used(node_asn *node); - -int -_asn1_set_default_tag(node_asn *node); - -/* prototypes - not defined elsewere */ -int _asn1_change_integer_value(node_asn *node); -int _asn1_expand_object_id(node_asn *node); -int _asn1_expand_identifier(node_asn **node,node_asn *root); -int _asn1_type_choice_config(node_asn *node); -int _asn1_type_set_config(node_asn *node); -int _asn1_check_identifier(node_asn *node); -int _asn1_create_static_structure(node_asn *pointer,char *file_name, char* out_name); - -int -asn1_parser_asn1(char *file_name,node_asn **pointer); - -int -asn1_create_structure(node_asn *root,char *source_name,node_asn **pointer, - char *dest_name); - -int -asn1_delete_structure(node_asn *root); - -int -asn1_write_value(node_asn *root,char *name,unsigned char *value,int len); - -int -asn1_read_value(node_asn *root,char *name,unsigned char *value,int *len); - -int -asn1_create_tree(const static_asn *root,node_asn **pointer); - -int -asn1_number_of_elements(node_asn *root,char *name,int *num); - -#endif - diff --git a/lib/defines.h b/lib/defines.h index 3b8acdc..cefa01e 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -1,14 +1,14 @@ /* * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos * - * This file is part of GNUTLS. + * This file is part of LIBASN1. * - * GNUTLS is free software; you can redistribute it and/or modify + * LIBASN1 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * GNUTLS is distributed in the hope that it will be useful, + * LIBASN1 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -91,4 +91,12 @@ typedef signed char int8; #include <mem.h> -#endif /* defines_h */ +#endif /* defines_h */ + + + + + + + + diff --git a/lib/der.c b/lib/der.c deleted file mode 100644 index 2aebab3..0000000 --- a/lib/der.c +++ /dev/null @@ -1,1417 +0,0 @@ -/* - * Copyright (C) 2000,2001 Fabio Fiorina - * - * This file is part of GNUTLS. - * - * GNUTLS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUTLS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - - -/*****************************************************/ -/* File: x509_der.c */ -/* Description: Functions to manage DER encoding */ -/*****************************************************/ - -#include <defines.h> -#include "der.h" -#include "asn1.h" -#include <gstr.h> - -#define TAG_BOOLEAN 0x01 -#define TAG_INTEGER 0x02 -#define TAG_SEQUENCE 0x10 -#define TAG_SET 0x11 -#define TAG_OCTET_STRING 0x04 -#define TAG_BIT_STRING 0x03 -#define TAG_UTCTime 0x17 -#define TAG_GENERALIZEDTime 0x18 -#define TAG_OBJECT_ID 0x06 -#define TAG_ENUMERATED 0x0A -#define TAG_NULL 0x05 - - -char * -_asn1_ltostr(long v,char *str) -{ - long d,r; - char temp[20]; - int count,k,start; - - if(v<0){ - str[0]='-'; - start=1; - v=-v; - } - else start=0; - - count=0; - do{ - d=v/10; - r=v-d*10; - temp[start+count]='0'+(char)r; - count++; - v=d; - }while(v); - - for(k=0;k<count;k++) str[k+start]=temp[start+count-k-1]; - str[count+start]=0; - return str; -} - - -void -_asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len) -{ - int k; - unsigned char temp[128]; - - if(len<128){ - /* short form */ - if(ans!=NULL) ans[0]=(unsigned char)len; - *ans_len=1; - } - else{ - /* Long form */ - k=0; - while(len){ - temp[k++]=len&0xFF; - len=len>>8; - } - *ans_len=k+1; - if(ans!=NULL){ - ans[0]=((unsigned char)k&0x7F)+128; - while(k--) ans[*ans_len-1-k]=temp[k]; - } - } -} - - -unsigned long -_asn1_get_length_der(unsigned char *der,int *len) -{ - unsigned long ans; - int k,punt; - - if(!(der[0]&128)){ - /* short form */ - *len=1; - return der[0]; - } - else{ - /* Long form */ - k=der[0]&0x7F; - punt=1; - ans=0; - while(punt<=k) ans=ans*256+der[punt++]; - - *len=punt; - return ans; - } -} - - -void -_asn1_tag_der(unsigned char class,unsigned int tag_value,unsigned char *ans,int *ans_len) -{ - int k; - unsigned char temp[128]; - - if(tag_value<30){ - /* short form */ - ans[0]=(class&0xE0) + ((unsigned char)(tag_value&0x1F)); - *ans_len=1; - } - else{ - /* Long form */ - ans[0]=(class&0xE0) + 31; - k=0; - while(tag_value){ - temp[k++]=tag_value&0x7F; - tag_value=tag_value>>7; - } - *ans_len=k+1; - while(k--) ans[*ans_len-1-k]=temp[k]+128; - ans[*ans_len-1]-=128; - } -} - - -unsigned int -_asn1_get_tag_der(unsigned char *der,unsigned char *class,int *len) -{ - int punt,ris; - - *class=der[0]&0xE0; - if((der[0]&0x1F)!=0x1F){ - /* short form */ - *len=1; - ris=der[0]&0x1F; - } - else{ - /* Long form */ - punt=1; - ris=0; - while(der[punt]&128) ris=ris*128+(der[punt++]&0x7F); - ris=ris*128+(der[punt++]&0x7F); - *len=punt; - } - return ris; -} - - -void -_asn1_octet_der(unsigned char *str,int str_len,unsigned char *der,int *der_len) -{ - int len_len; - - if(der==NULL) return; - _asn1_length_der(str_len,der,&len_len); - memcpy(der+len_len,str,str_len); - *der_len=str_len+len_len; -} - - -int -_asn1_get_octet_der(unsigned char *der,int *der_len,unsigned char *str,int str_size, int *str_len) -{ - int len_len; - - if(str==NULL) return ASN_OK; - *str_len=_asn1_get_length_der(der,&len_len); - if ( str_size >= *str_len) - memcpy(str,der+len_len,*str_len); - else { - return ASN_MEM_ERROR; - } - *der_len=*str_len+len_len; - - return ASN_OK; -} - - -void -_asn1_time_der(unsigned char *str,unsigned char *der,int *der_len) -{ - int len_len; - - if(der==NULL) return; - _asn1_length_der(strlen(str),der,&len_len); - memcpy(der+len_len,str,strlen(str)); - *der_len=len_len+strlen(str); -} - - -/* -void -_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) -{ - int len_len,str_len; - char temp[20]; - - if(str==NULL) return; - str_len=_asn1_get_length_der(der,&len_len); - memcpy(temp,der+len_len,str_len); - *der_len=str_len+len_len; - switch(str_len){ - case 11: - temp[10]=0; - strcat(temp,"00+0000"); - break; - case 13: - temp[12]=0; - strcat(temp,"+0000"); - break; - case 15: - temp[15]=0; - memmove(temp+12,temp+10,6); - temp[10]=temp[11]='0'; - break; - case 17: - temp[17]=0; - break; - default: - return; - } - strcpy(str,temp); -} -*/ - - -void -_asn1_get_time_der(unsigned char *der,int *der_len,unsigned char *str) -{ - int len_len,str_len; - - if(str==NULL) return; - str_len=_asn1_get_length_der(der,&len_len); - memcpy(str,der+len_len,str_len); - str[str_len]=0; - *der_len=str_len+len_len; -} - -void -_asn1_objectid_der(unsigned char *str,unsigned char *der,int *der_len) -{ - int len_len,counter,k,first; - char temp[128],*n_end,*n_start; - unsigned char bit7; - unsigned long val,val1=0; - - if(der==NULL) return; - - _asn1_str_cpy(temp, sizeof(temp), str); - _asn1_str_cat(temp, sizeof(temp), " "); - - counter=0; - n_start=temp; - while((n_end=strchr(n_start,' '))){ - *n_end=0; - val=strtoul(n_start,NULL,10); - counter++; - - if(counter==1) val1=val; - else if(counter==2){ - der[0]=40*val1+val; - *der_len=1; - } - else{ - first=0; - for(k=4;k>=0;k--){ - bit7=(val>>(k*7))&0x7F; - if(bit7 || first || !k){ - if(k) bit7|=0x80; - der[*der_len]=bit7; - (*der_len)++; - first=1; - } - } - - } - n_start=n_end+1; - } - - _asn1_length_der(*der_len,NULL,&len_len); - memmove(der+len_len,der,*der_len); - _asn1_length_der(*der_len,der,&len_len); - *der_len+=len_len; -} - - -void -_asn1_get_objectid_der(unsigned char *der,int *der_len,unsigned char *str, int str_size) -{ - int len_len,len,k; - char temp[20]; - unsigned long val,val1; - - if(str==NULL) return; - len=_asn1_get_length_der(der,&len_len); - - val1=der[len_len]/40; - val=der[len_len]-val1*40; - - _asn1_str_cpy(str, str_size, _asn1_ltostr(val1,temp)); - _asn1_str_cat(str, str_size, " "); - _asn1_str_cat(str, str_size, _asn1_ltostr(val,temp)); - - val=0; - for(k=1;k<len;k++){ - val=val<<7; - val|=der[len_len+k]&0x7F; - if(!(der[len_len+k]&0x80)){ - _asn1_str_cat(str, str_size," "); - _asn1_str_cat(str, str_size,_asn1_ltostr(val,temp)); - val=0; - } - } - *der_len=len+len_len; -} - - - -char bit_mask[]={0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80}; - -void -_asn1_bit_der(unsigned char *str,int bit_len,unsigned char *der,int *der_len) -{ - int len_len,len_byte,len_pad; - - if(der==NULL) return; - len_byte=bit_len>>3; - len_pad=8-(bit_len&7); - if(len_pad==8) len_pad=0; - else len_byte++; - _asn1_length_der(len_byte+1,der,&len_len); - der[len_len]=len_pad; - memcpy(der+len_len+1,str,len_byte); - der[len_len+len_byte]&=bit_mask[len_pad]; - *der_len=len_byte+len_len+1; -} - - -int -_asn1_get_bit_der(unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len) -{ - int len_len,len_byte; - - if(str==NULL) return ASN_OK; - len_byte=_asn1_get_length_der(der,&len_len)-1; - - if (str_size >= len_byte) - memcpy(str,der+len_len+1,len_byte); - else { - return ASN_MEM_ERROR; - } - *bit_len=len_byte*8-der[len_len]; - *der_len=len_byte+len_len+1; - - return ASN_OK; -} - - - - -#define UP 1 -#define DOWN 2 -#define RIGHT 3 - - -void -_asn1_complete_explicit_tag(node_asn *node,unsigned char *der,int *counter) -{ - node_asn *p; - int is_tag_implicit,len2,len3; - unsigned char temp[10]; - - is_tag_implicit=0; - - if(node->type&CONST_TAG){ - p=node->down; - while(p){ - if(type_field(p->type)==TYPE_TAG){ - if(p->type&CONST_EXPLICIT){ - len2=strtol(p->name,NULL,10); - _asn1_set_name(p,NULL); - _asn1_length_der(*counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,*counter-len2); - memcpy(der+len2,temp,len3); - *counter+=len3; - is_tag_implicit=0; - } - else{ /* CONST_IMPLICIT */ - if(!is_tag_implicit){ - is_tag_implicit=1; - } - } - } - p=p->right; - } - } -} - - -int -_asn1_insert_tag_der(node_asn *node,unsigned char *der,int *counter) -{ - node_asn *p; - int tag_len,is_tag_implicit; - unsigned char class,class_implicit=0,temp[10]; - unsigned long tag_implicit=0; - - is_tag_implicit=0; - - if(node->type&CONST_TAG){ - p=node->down; - while(p){ - if(type_field(p->type)==TYPE_TAG){ - if(p->type&CONST_APPLICATION) class=APPLICATION; - else if(p->type&CONST_UNIVERSAL) class=UNIVERSAL; - else if(p->type&CONST_PRIVATE) class=PRIVATE; - else class=CONTEXT_SPECIFIC; - - if(p->type&CONST_EXPLICIT){ - if(is_tag_implicit) - _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len); - else - _asn1_tag_der(class|STRUCTURED,strtoul(p->value,NULL,10),der+*counter,&tag_len); - *counter+=tag_len; - _asn1_ltostr(*counter,temp); - _asn1_set_name(p,temp); - - is_tag_implicit=0; - } - else{ /* CONST_IMPLICIT */ - if(!is_tag_implicit){ - if((type_field(node->type)==TYPE_SEQUENCE) || - (type_field(node->type)==TYPE_SEQUENCE_OF) || - (type_field(node->type)==TYPE_SET) || - (type_field(node->type)==TYPE_SET_OF)) class|=STRUCTURED; - class_implicit=class; - tag_implicit=strtoul(p->value,NULL,10); - is_tag_implicit=1; - } - } - } - p=p->right; - } - } - - if(is_tag_implicit){ - _asn1_tag_der(class_implicit,tag_implicit,der+*counter,&tag_len); - } - else{ - switch(type_field(node->type)){ - case TYPE_NULL: - _asn1_tag_der(UNIVERSAL,TAG_NULL,der+*counter,&tag_len); - break; - case TYPE_BOOLEAN: - _asn1_tag_der(UNIVERSAL,TAG_BOOLEAN,der+*counter,&tag_len); - break; - case TYPE_INTEGER: - _asn1_tag_der(UNIVERSAL,TAG_INTEGER,der+*counter,&tag_len); - break; - case TYPE_ENUMERATED: - _asn1_tag_der(UNIVERSAL,TAG_ENUMERATED,der+*counter,&tag_len); - break; - case TYPE_OBJECT_ID: - _asn1_tag_der(UNIVERSAL,TAG_OBJECT_ID,der+*counter,&tag_len); - break; - case TYPE_TIME: - if(node->type&CONST_UTC){ - _asn1_tag_der(UNIVERSAL,TAG_UTCTime,der+*counter,&tag_len); - } - else _asn1_tag_der(UNIVERSAL,TAG_GENERALIZEDTime,der+*counter,&tag_len); - break; - case TYPE_OCTET_STRING: - _asn1_tag_der(UNIVERSAL,TAG_OCTET_STRING,der+*counter,&tag_len); - break; - case TYPE_BIT_STRING: - _asn1_tag_der(UNIVERSAL,TAG_BIT_STRING,der+*counter,&tag_len); - break; - case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF: - _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SEQUENCE,der+*counter,&tag_len); - break; - case TYPE_SET: case TYPE_SET_OF: - _asn1_tag_der(UNIVERSAL|STRUCTURED,TAG_SET,der+*counter,&tag_len); - break; - case TYPE_TAG: - tag_len=0; - break; - case TYPE_CHOICE: - tag_len=0; - break; - case TYPE_ANY: - tag_len=0; - break; - default: - return ASN_GENERIC_ERROR; - } - } - - *counter+=tag_len; - - return ASN_OK; -} - - -int -_asn1_extract_tag_der(node_asn *node,unsigned char *der,int *der_len) -{ - node_asn *p; - int counter,len2,len3,is_tag_implicit; - unsigned long tag,tag_implicit=0; - unsigned char class,class2,class_implicit=0; - - counter=is_tag_implicit=0; - if(node->type&CONST_TAG){ - p=node->down; - while(p){ - if(type_field(p->type)==TYPE_TAG){ - if(p->type&CONST_APPLICATION) class2=APPLICATION; - else if(p->type&CONST_UNIVERSAL) class2=UNIVERSAL; - else if(p->type&CONST_PRIVATE) class2=PRIVATE; - else class2=CONTEXT_SPECIFIC; - - if(p->type&CONST_EXPLICIT){ - tag=_asn1_get_tag_der(der+counter,&class,&len2); - counter+=len2; - len3=_asn1_get_length_der(der+counter,&len2); - counter+=len2; - if(!is_tag_implicit){ - if((class!=(class2|STRUCTURED)) || (tag!=strtoul(p->value,NULL,10))) - return ASN_TAG_ERROR; - } - else{ /* TAG_IMPLICIT */ - if((class!=class_implicit) || (tag!=tag_implicit)) - return ASN_TAG_ERROR; - } - - is_tag_implicit=0; - } - else{ /* TAG_IMPLICIT */ - if(!is_tag_implicit){ - if((type_field(node->type)==TYPE_SEQUENCE) || - (type_field(node->type)==TYPE_SEQUENCE_OF) || - (type_field(node->type)==TYPE_SET) || - (type_field(node->type)==TYPE_SET_OF)) class2|=STRUCTURED; - class_implicit=class2; - tag_implicit=strtoul(p->value,NULL,10); - is_tag_implicit=1; - } - } - } - p=p->right; - } - } - - if(is_tag_implicit){ - tag=_asn1_get_tag_der(der+counter,&class,&len2); - if((class!=class_implicit) || (tag!=tag_implicit)) return ASN_TAG_ERROR; - } - else{ - if(type_field(node->type)==TYPE_TAG){ - counter=0; - *der_len=counter; - return ASN_OK; - } - - tag=_asn1_get_tag_der(der+counter,&class,&len2); - switch(type_field(node->type)){ - case TYPE_NULL: - if((class!=UNIVERSAL) || (tag!=TAG_NULL)) return ASN_DER_ERROR; - break; - case TYPE_BOOLEAN: - if((class!=UNIVERSAL) || (tag!=TAG_BOOLEAN)) return ASN_DER_ERROR; - break; - case TYPE_INTEGER: - if((class!=UNIVERSAL) || (tag!=TAG_INTEGER)) return ASN_DER_ERROR; - break; - case TYPE_ENUMERATED: - if((class!=UNIVERSAL) || (tag!=TAG_ENUMERATED)) return ASN_DER_ERROR; - break; - case TYPE_OBJECT_ID: - if((class!=UNIVERSAL) || (tag!=TAG_OBJECT_ID)) return ASN_DER_ERROR; - break; - case TYPE_TIME: - if(node->type&CONST_UTC){ - if((class!=UNIVERSAL) || (tag!=TAG_UTCTime)) return ASN_DER_ERROR; - } - else{ - if((class!=UNIVERSAL) || (tag!=TAG_GENERALIZEDTime)) - return ASN_DER_ERROR; - } - break; - case TYPE_OCTET_STRING: - if((class!=UNIVERSAL) || (tag!=TAG_OCTET_STRING)) return ASN_DER_ERROR; - break; - case TYPE_BIT_STRING: - if((class!=UNIVERSAL) || (tag!=TAG_BIT_STRING)) return ASN_DER_ERROR; - break; - case TYPE_SEQUENCE: case TYPE_SEQUENCE_OF: - if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SEQUENCE)) - return ASN_DER_ERROR; - break; - case TYPE_SET: case TYPE_SET_OF: - if((class!=(UNIVERSAL|STRUCTURED)) || (tag!=TAG_SET)) - return ASN_DER_ERROR; - break; - case TYPE_ANY: - counter-=len2; - break; - default: - return ASN_DER_ERROR; - break; - } - } - - counter+=len2; - *der_len=counter; - return ASN_OK; -} - - -void -_asn1_ordering_set(unsigned char *der,node_asn *node) -{ - struct vet{ - int end; - unsigned long value; - struct vet *next,*prev; - }; - - int counter,len,len2; - struct vet *first,*last,*p_vet,*p2_vet; - node_asn *p; - unsigned char class,*temp; - unsigned long tag; - - counter=0; - - if(type_field(node->type)!=TYPE_SET) return; - - p=node->down; - while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right; - - if((p==NULL) || (p->right==NULL)) return; - - first=last=NULL; - while(p){ - p_vet=(struct vet *)_asn1_alloca( sizeof(struct vet)); - if (p_vet==NULL) return; - - p_vet->next=NULL; - p_vet->prev=last; - if(first==NULL) first=p_vet; - else last->next=p_vet; - last=p_vet; - - /* tag value calculation */ - tag=_asn1_get_tag_der(der+counter,&class,&len2); - p_vet->value=(class<<24)|tag; - counter+=len2; - - /* extraction and length */ - len2=_asn1_get_length_der(der+counter,&len); - counter+=len+len2; - - p_vet->end=counter; - p=p->right; - } - - p_vet=first; - - while(p_vet){ - p2_vet=p_vet->next; - counter=0; - while(p2_vet){ - if(p_vet->value>p2_vet->value){ - /* change position */ - temp=(unsigned char *)_asn1_alloca( p_vet->end-counter); - if (temp==NULL) return; - - memcpy(temp,der+counter,p_vet->end-counter); - memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end); - memcpy(der+p_vet->end,temp,p_vet->end-counter); - _asn1_afree(temp); - - tag=p_vet->value; - p_vet->value=p2_vet->value; - p2_vet->value=tag; - - p_vet->end=counter+(p2_vet->end-p_vet->end); - } - counter=p_vet->end; - - p2_vet=p2_vet->next; - p_vet=p_vet->next; - } - - if(p_vet!=first) p_vet->prev->next=NULL; - else first=NULL; - _asn1_afree(p_vet); - p_vet=first; - } -} - - -void -_asn1_ordering_set_of(unsigned char *der,node_asn *node) -{ - struct vet{ - int end; - struct vet *next,*prev; - }; - - int counter,len,len2,change; - struct vet *first,*last,*p_vet,*p2_vet; - node_asn *p; - unsigned char *temp,class; - unsigned long k,max; - - counter=0; - - if(type_field(node->type)!=TYPE_SET_OF) return; - - p=node->down; - while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right; - p=p->right; - - if((p==NULL) || (p->right==NULL)) return; - - first=last=NULL; - while(p){ - p_vet=(struct vet *)_asn1_alloca(sizeof(struct vet)); - if (p_vet==NULL) return; - - p_vet->next=NULL; - p_vet->prev=last; - if(first==NULL) first=p_vet; - else last->next=p_vet; - last=p_vet; - - /* extraction of tag and length */ - _asn1_get_tag_der(der+counter,&class,&len); - counter+=len; - len2=_asn1_get_length_der(der+counter,&len); - counter+=len+len2; - - p_vet->end=counter; - p=p->right; - } - - p_vet=first; - - while(p_vet){ - p2_vet=p_vet->next; - counter=0; - while(p2_vet){ - if((p_vet->end-counter)>(p2_vet->end-p_vet->end)) - max=p_vet->end-counter; - else - max=p2_vet->end-p_vet->end; - - change=-1; - for(k=0;k<max;k++) - if(der[counter+k]>der[p_vet->end+k]){change=1;break;} - else if(der[counter+k]<der[p_vet->end+k]){change=0;break;} - - if((change==-1) && ((p_vet->end-counter)>(p2_vet->end-p_vet->end))) - change=1; - - if(change==1){ - /* change position */ - temp=(unsigned char *)_asn1_alloca(p_vet->end-counter); - if (temp==NULL) return; - - memcpy(temp,der+counter,p_vet->end-counter); - memmove(der+counter,der+p_vet->end,p2_vet->end-p_vet->end); - memcpy(der+p_vet->end,temp,p_vet->end-counter); - _asn1_afree(temp); - - p_vet->end=counter+(p2_vet->end-p_vet->end); - } - counter=p_vet->end; - - p2_vet=p2_vet->next; - p_vet=p_vet->next; - } - - if(p_vet!=first) p_vet->prev->next=NULL; - else first=NULL; - _asn1_afree(p_vet); - p_vet=first; - } -} - -/** - * asn1_create_der - Creates the DER encoding for the NAME structure - * @root: pointer to a structure - * @name: the name of the structure you want to encode (it must be inside *POINTER). - * @der: vector that will contain the DER encoding. DER must be a pointer to memory cells already allocated. - * @len: number of bytes of *der: der[0]..der[len-1] - * Description: - * - * Creates the DER encoding for the NAME structure (inside *POINTER structure). - * - * Returns: - * - * ASN_OK\: DER encoding OK - * - * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element. - * - * ASN_VALUE_NOT_FOUND\: there is an element without a value. - **/ -int -asn1_create_der(node_asn *root,char *name,unsigned char *der,int *len) -{ - node_asn *node,*p; - char temp[20]; - int counter,counter_old,len2,len3,move,ris; - - node=_asn1_find_node(root,name); - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - counter=0; - move=DOWN; - p=node; - while(1){ - - counter_old=counter; - if(move!=UP) ris=_asn1_insert_tag_der(p,der,&counter); - - switch(type_field(p->type)){ - case TYPE_NULL: - der[counter]=0; - counter++; - move=RIGHT; - break; - case TYPE_BOOLEAN: - if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; - else{ - der[counter++]=1; - if(p->value[0]=='F') der[counter++]=0; - else der[counter++]=0xFF; - } - move=RIGHT; - break; - case TYPE_INTEGER: case TYPE_ENUMERATED: - if((p->type&CONST_DEFAULT) && (p->value==NULL)) counter=counter_old; - else{ - len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); - counter+=len3+len2; - } - move=RIGHT; - break; - case TYPE_OBJECT_ID: - _asn1_objectid_der(p->value,der+counter,&len2); - counter+=len2; - move=RIGHT; - break; - case TYPE_TIME: - _asn1_time_der(p->value,der+counter,&len2); - counter+=len2; - move=RIGHT; - break; - case TYPE_OCTET_STRING: - len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_BIT_STRING: - len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value,len3+len2); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_SEQUENCE: case TYPE_SET: - if(move!=UP){ - _asn1_ltostr(counter,temp); - _asn1_set_value(p,temp,strlen(temp)+1); - move=DOWN; - } - else{ /* move==UP */ - len2=strtol(p->value,NULL,10); - _asn1_set_value(p,NULL,0); - if(type_field(p->type)==TYPE_SET) _asn1_ordering_set(der+len2,p); - _asn1_length_der(counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,counter-len2); - memcpy(der+len2,temp,len3); - counter+=len3; - move=RIGHT; - } - break; - case TYPE_SEQUENCE_OF: case TYPE_SET_OF: - if(move!=UP){ - _asn1_ltostr(counter,temp); - _asn1_set_value(p,temp,strlen(temp)+1); - p=p->down; - while((type_field(p->type)==TYPE_TAG) || (type_field(p->type)==TYPE_SIZE)) p=p->right; - if(p->right){ - p=p->right; - move=RIGHT; - continue; - } - else p=_asn1_find_up(p); - move=UP; - } - if(move==UP){ - len2=strtol(p->value,NULL,10); - _asn1_set_value(p,NULL,0); - if(type_field(p->type)==TYPE_SET_OF) _asn1_ordering_set_of(der+len2,p); - _asn1_length_der(counter-len2,temp,&len3); - memmove(der+len2+len3,der+len2,counter-len2); - memcpy(der+len2,temp,len3); - counter+=len3; - move=RIGHT; - } - break; - case TYPE_ANY: - len2=_asn1_get_length_der(p->value,&len3); - memcpy(der+counter,p->value+len3,len2); - counter+=len2; - move=RIGHT; - break; - default: - move=(move==UP)?RIGHT:DOWN; - break; - } - - if((move!=DOWN) && (counter!=counter_old)) - _asn1_complete_explicit_tag(p,der,&counter); - - if(p==node && move!=DOWN) break; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - if(move==RIGHT){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - *len=counter; - return ASN_OK; -} - -/** - * asn1_get_der - Fill the structure *POINTER with values of a DER encoding string. - * @root: pointer to a structure - * @der: vector that contains the DER encoding. - * @len: number of bytes of *der: der[0]..der[len-1] - * Description: - * - * Fill the structure *POINTER with values of a DER encoding string. The sructure must just be - * created with function 'create_stucture'. - * - * Returns: - * - * ASN_OK\: DER encoding OK - * - * ASN_ELEMENT_NOT_FOUND\: NAME is not a valid element. - * - * ASN_TAG_ERROR,ASN_DER_ERROR\: the der encoding doesn't match the structure NAME. - **/ - -int -asn1_get_der(node_asn *root,unsigned char *der,int len) -{ - node_asn *node,*p,*p2,*p3; - char temp[128]; - int counter,len2,len3,len4,move,ris; - unsigned char class,*temp2; - unsigned int tag; - - node=root; - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - if(node->type&CONST_OPTION) return ASN_GENERIC_ERROR; - - counter=0; - move=DOWN; - p=node; - while(1){ - ris=ASN_OK; - - if(move!=UP){ - if(p->type&CONST_SET){ - p2=_asn1_find_up(p); - len2=strtol(p2->value,NULL,10); - if(counter==len2){ - p=p2; - move=UP; - continue; - } - else if(counter>len2) return ASN_DER_ERROR; - p2=p2->down; - while(p2){ - if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){ /* CONTROLLARE */ - if(type_field(p2->type)!=TYPE_CHOICE) - ris=_asn1_extract_tag_der(p2,der+counter,&len2); - else{ - p3=p2->down; - while(p3){ - ris=_asn1_extract_tag_der(p3,der+counter,&len2); - if(ris==ASN_OK) break; - //if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY; - p3=p3->right; - } - } - if(ris==ASN_OK){ - p2->type&=~CONST_NOT_USED; - p=p2; - break; - } - //else if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY; - } - p2=p2->right; - } - if(p2==NULL) return ASN_DER_ERROR; - } - - if(type_field(p->type)==TYPE_CHOICE){ - while(p->down){ - ris=_asn1_extract_tag_der(p->down,der+counter,&len2); - if(ris==ASN_OK){ - while(p->down->right) asn1_delete_structure(p->down->right); - break; - } - else if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY; - else asn1_delete_structure(p->down); - } - if(p->down==NULL) return ASN_DER_ERROR; - p=p->down; - } - - if((p->type&CONST_OPTION) || (p->type&CONST_DEFAULT)){ - p2=_asn1_find_up(p); - len2=strtol(p2->value,NULL,10); - if(counter>=len2) ris=ASN_TAG_ERROR; - } - - if(ris==ASN_OK) ris=_asn1_extract_tag_der(p,der+counter,&len2); - if(ris!=ASN_OK){ - //if(ris==ASN_ERROR_TYPE_ANY) return ASN_ERROR_TYPE_ANY; - if(p->type&CONST_OPTION){ - p->type|=CONST_NOT_USED; - move=RIGHT; - } - else if(p->type&CONST_DEFAULT) { - _asn1_set_value(p,NULL,0); - move=RIGHT; - } - else { - //return (type_field(p->type)!=TYPE_ANY)?ASN_TAG_ERROR:ASN_ERROR_TYPE_ANY; - return ASN_TAG_ERROR; - } - } - else counter+=len2; - } - - if(ris==ASN_OK){ - switch(type_field(p->type)){ - case TYPE_NULL: - if(der[counter]) return ASN_DER_ERROR; - counter++; - move=RIGHT; - break; - case TYPE_BOOLEAN: - if(der[counter++]!=1) return ASN_DER_ERROR; - if(der[counter++]==0) _asn1_set_value(p,"F",1); - else _asn1_set_value(p,"T",1); - move=RIGHT; - break; - case TYPE_INTEGER: case TYPE_ENUMERATED: - len2=_asn1_get_length_der(der+counter,&len3); - _asn1_set_value(p,der+counter,len3+len2); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_OBJECT_ID: - _asn1_get_objectid_der(der+counter,&len2, temp, sizeof(temp)); - _asn1_set_value(p,temp,strlen(temp)+1); - counter+=len2; - move=RIGHT; - break; - case TYPE_TIME: - _asn1_get_time_der(der+counter,&len2,temp); - _asn1_set_value(p,temp,strlen(temp)+1); - counter+=len2; - move=RIGHT; - break; - case TYPE_OCTET_STRING: - len2=_asn1_get_length_der(der+counter,&len3); - _asn1_set_value(p,der+counter,len3+len2); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_BIT_STRING: - len2=_asn1_get_length_der(der+counter,&len3); - _asn1_set_value(p,der+counter,len3+len2); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_SEQUENCE: case TYPE_SET:; - if(move==UP){ - len2=strtol(p->value,NULL,10); - _asn1_set_value(p,NULL,0); - if(len2!=counter) return ASN_DER_ERROR; - move=RIGHT; - } - else{ /* move==DOWN || move==RIGHT */ - len3=_asn1_get_length_der(der+counter,&len2); - counter+=len2; - _asn1_ltostr(counter+len3,temp); - _asn1_set_value(p,temp,strlen(temp)+1); - move=DOWN; - } - break; - case TYPE_SEQUENCE_OF: case TYPE_SET_OF: - if(move==UP){ - len2=strtol(p->value,NULL,10); - if(len2>counter){ - _asn1_append_sequence_set(p); - p=p->down; - while(p->right) p=p->right; - move=RIGHT; - continue; - } - _asn1_set_value(p,NULL,0); - if(len2!=counter) return ASN_DER_ERROR; - } - else{ /* move==DOWN || move==RIGHT */ - len3=_asn1_get_length_der(der+counter,&len2); - counter+=len2; - if(len3){ - _asn1_ltostr(counter+len3,temp); - _asn1_set_value(p,temp,strlen(temp)+1); - p2=p->down; - while((type_field(p2->type)==TYPE_TAG) || (type_field(p2->type)==TYPE_SIZE)) p2=p2->right; - if(p2->right==NULL) _asn1_append_sequence_set(p); - p=p2; - } - } - move=RIGHT; - break; - case TYPE_ANY: - tag=_asn1_get_tag_der(der+counter,&class,&len2); - len2+=_asn1_get_length_der(der+counter+len2,&len3); - _asn1_length_der(len2+len3,NULL,&len4); - temp2=(unsigned char *)_asn1_alloca(len2+len3+len4); - if (temp2==NULL) return ASN_MEM_ERROR; - - _asn1_octet_der(der+counter,len2+len3,temp2,&len4); - _asn1_set_value(p,temp2,len4); - _asn1_afree(temp2); - counter+=len2+len3; - move=RIGHT; - break; - default: - move=(move==UP)?RIGHT:DOWN; - break; - } - } - - if(p==node && move!=DOWN) break; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - if((move==RIGHT) && !(p->type&CONST_SET)){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - _asn1_delete_not_used(root); - - return (counter==len)?ASN_OK:ASN_DER_ERROR; -} - - -/** - * asn1_get_start_end_der - Find the start and end point of an element in a DER encoding string. - * @root: pointer to a structure - * @der: vector that contains the DER encoding. - * @len: number of bytes of *der: der[0]..der[len-1] - * @name_element: an element of NAME structure. - * @start: the position of the first byte of NAME_ELEMENT decoding (der[*start]) - * @end: the position of the last byte of NAME_ELEMENT decoding (der[*end]) - * Description: - * - * Find the start and end point of an element in a DER encoding string. I mean that if you - * have a der encoding and you have already used the function "get_der" to fill a structure, it may - * happen that you want to find the piece of string concerning an element of the structure. - * - * Example: the sequence "tbsCertificate" inside an X509 certificate. - * - * Returns: - * - * ASN_OK\: DER encoding OK - * - * ASN_ELEMENT_NOT_FOUND\: NAME or NAME_ELEMENT is not a valid element. - * - * ASN_TAG_ERROR,ASN_DER_ERROR\: the der encoding doesn't match the structure NAME. - * - **/ -int -asn1_get_start_end_der(node_asn *root,unsigned char *der,int len,char *name_element,int *start, int *end) -{ - node_asn *node,*node_to_find,*p,*p2,*p3; - int counter,len2,len3,move,ris; - unsigned char class; - unsigned int tag; - - node=root; - node_to_find=_asn1_find_node(root,name_element); - - if(node_to_find==NULL) return ASN_ELEMENT_NOT_FOUND; - - if(node_to_find==node){ - *start=0; - *end=len-1; - return ASN_OK; - } - - if(node==NULL) return ASN_ELEMENT_NOT_FOUND; - - if(node->type&CONST_OPTION) return ASN_GENERIC_ERROR; - - counter=0; - move=DOWN; - p=node; - while(1){ - ris=ASN_OK; - - if(move!=UP){ - if(p->type&CONST_SET){ - p2=_asn1_find_up(p); - len2=strtol(p2->value,NULL,10); - if(counter==len2){ - p=p2; - move=UP; - continue; - } - else if(counter>len2) return ASN_DER_ERROR; - p2=p2->down; - while(p2){ - if((p2->type&CONST_SET) && (p2->type&CONST_NOT_USED)){ /* CONTROLLARE */ - if(type_field(p2->type)!=TYPE_CHOICE) - ris=_asn1_extract_tag_der(p2,der+counter,&len2); - else{ - p3=p2->down; - ris=_asn1_extract_tag_der(p3,der+counter,&len2); - } - if(ris==ASN_OK){ - p2->type&=~CONST_NOT_USED; - p=p2; - break; - } - } - p2=p2->right; - } - if(p2==NULL) return ASN_DER_ERROR; - } - - if(p==node_to_find) *start=counter; - - if(type_field(p->type)==TYPE_CHOICE){ - p=p->down; - ris=_asn1_extract_tag_der(p,der+counter,&len2); - if(p==node_to_find) *start=counter; - } - - if(ris==ASN_OK) ris=_asn1_extract_tag_der(p,der+counter,&len2); - if(ris!=ASN_OK){ - if(p->type&CONST_OPTION){ - p->type|=CONST_NOT_USED; - move=RIGHT; - } - else if(p->type&CONST_DEFAULT) { - move=RIGHT; - } - else { - return ASN_TAG_ERROR; - } - } - else counter+=len2; - } - - if(ris==ASN_OK){ - switch(type_field(p->type)){ - case TYPE_NULL: - if(der[counter]) return ASN_DER_ERROR; - counter++; - move=RIGHT; - break; - case TYPE_BOOLEAN: - if(der[counter++]!=1) return ASN_DER_ERROR; - counter++; - move=RIGHT; - break; - case TYPE_INTEGER: case TYPE_ENUMERATED: - len2=_asn1_get_length_der(der+counter,&len3); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_OBJECT_ID: - len2=_asn1_get_length_der(der+counter,&len3); - counter+=len2+len3; - move=RIGHT; - break; - case TYPE_TIME: - len2=_asn1_get_length_der(der+counter,&len3); - counter+=len2+len3; - move=RIGHT; - break; - case TYPE_OCTET_STRING: - len2=_asn1_get_length_der(der+counter,&len3); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_BIT_STRING: - len2=_asn1_get_length_der(der+counter,&len3); - counter+=len3+len2; - move=RIGHT; - break; - case TYPE_SEQUENCE: case TYPE_SET: - if(move!=UP){ - len3=_asn1_get_length_der(der+counter,&len2); - counter+=len2; - move=DOWN; - } - else move=RIGHT; - break; - case TYPE_SEQUENCE_OF: case TYPE_SET_OF: - if(move!=UP){ - len3=_asn1_get_length_der(der+counter,&len2); - counter+=len2; - if(len3){ - p2=p->down; - while((type_field(p2->type)==TYPE_TAG) || - (type_field(p2->type)==TYPE_SIZE)) p2=p2->right; - p=p2; - } - } - move=RIGHT; - break; - case TYPE_ANY: - tag=_asn1_get_tag_der(der+counter,&class,&len2); - len2+=_asn1_get_length_der(der+counter+len2,&len3); - counter+=len3+len2; - move=RIGHT; - break; - default: - move=(move==UP)?RIGHT:DOWN; - break; - } - } - - if((p==node_to_find) && (move==RIGHT)){ - *end=counter-1; - return ASN_OK; - } - - if(p==node && move!=DOWN) break; - - if(move==DOWN){ - if(p->down) p=p->down; - else move=RIGHT; - } - if((move==RIGHT) && !(p->type&CONST_SET)){ - if(p->right) p=p->right; - else move=UP; - } - if(move==UP) p=_asn1_find_up(p); - } - - return ASN_ELEMENT_NOT_FOUND; -} - - - - - - - - - - @@ -1,13 +1,12 @@ /*************************************************/ -/* File: x509_der.h */ -/* Description: list of exported object by */ -/* "x509_der.c" */ +/* File: der.h */ +/* Description: list of definitions and exported */ +/* objects by coding.c and decoding.c */ /*************************************************/ -#ifndef _GNUTLS_DER_H -#define _GNUTLS_DER_H +#ifndef _DER_H +#define _DER_H -#include "asn1.h" #define UNIVERSAL 0x00 #define APPLICATION 0x40 @@ -16,35 +15,38 @@ #define STRUCTURED 0x20 -void -_asn1_octet_der(unsigned char *str,int str_len,unsigned char *der,int *der_len); +#define TAG_BOOLEAN 0x01 +#define TAG_INTEGER 0x02 +#define TAG_SEQUENCE 0x10 +#define TAG_SET 0x11 +#define TAG_OCTET_STRING 0x04 +#define TAG_BIT_STRING 0x03 +#define TAG_UTCTime 0x17 +#define TAG_GENERALIZEDTime 0x18 +#define TAG_OBJECT_ID 0x06 +#define TAG_ENUMERATED 0x0A +#define TAG_NULL 0x05 -int -_asn1_get_octet_der(unsigned char *der,int *der_len,unsigned char *str,int str_size, int *str_len); +unsigned int _asn1_get_tag_der(unsigned char *der, + unsigned char *class,int *len); -void -_asn1_bit_der(unsigned char *str,int bit_len,unsigned char *der,int *der_len); +void _asn1_octet_der(unsigned char *str,int str_len, + unsigned char *der,int *der_len); -int -_asn1_get_bit_der(unsigned char *der,int *der_len,unsigned char *str, int str_size, int *bit_len); +asn1_retCode _asn1_get_octet_der(unsigned char *der, + int *der_len,unsigned char *str,int str_size, int *str_len); -int -asn1_create_der(node_asn *root,char *name,unsigned char *der,int *len); +void _asn1_bit_der(unsigned char *str,int bit_len, + unsigned char *der,int *der_len); -int -asn1_get_der(node_asn *root,unsigned char *der,int len); +asn1_retCode _asn1_get_bit_der(unsigned char *der, + int *der_len,unsigned char *str, int str_size, + int *bit_len); -int -asn1_get_start_end_der(node_asn *root,unsigned char *der,int len,char *name_element,int *start, int *end); +unsigned long _asn1_get_length_der(unsigned char *der,int *len); -unsigned long -_asn1_get_length_der(unsigned char *der,int *len); +void _asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len); -void -_asn1_length_der(unsigned long len,unsigned char *ans,int *ans_len); - -char * -_asn1_ltostr(long v,char *str); #endif @@ -1,14 +1,14 @@ /* * Copyright (C) 2002 Nikos Mavroyanopoulos * - * This file is part of GNUTLS. + * This file is part of LIBASN1. * - * GNUTLS is free software; you can redistribute it and/or modify + * LIBASN1 is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * GNUTLS is distributed in the hope that it will be useful, + * LIBASN1 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. @@ -64,3 +64,14 @@ void _asn1_mem_cpy( char* dest, size_t dest_tot_size, const char* src, size_t sr } } } + + + + + + + + + + + @@ -20,3 +20,5 @@ #define _asn1_strdup strdup #endif /* MEM_H */ + + |