diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2002-11-12 13:34:51 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2002-11-12 13:34:51 +0000 |
commit | 9ea1b87862f286932544180cbf6a80a510266831 (patch) | |
tree | d56a7e459b962b2c4ef8f2dc408dceaccc96c9aa | |
parent | 688cf84d1f5f0ceffd72c9ce43f7de870e9f5da5 (diff) |
Initial ASN1 generation code. This can construct
arbitrary encodings from strings and config files.
Documentation to follow...
-rw-r--r-- | apps/asn1pars.c | 115 | ||||
-rw-r--r-- | crypto/asn1/Makefile.ssl | 4 | ||||
-rw-r--r-- | crypto/asn1/asn1.h | 32 | ||||
-rw-r--r-- | crypto/asn1/asn1_err.c | 29 | ||||
-rw-r--r-- | crypto/asn1/asn1_gen.c | 831 | ||||
-rw-r--r-- | crypto/conf/conf.h | 3 | ||||
-rw-r--r-- | crypto/ossl_typ.h | 3 | ||||
-rw-r--r-- | crypto/x509v3/v3_alt.c | 36 | ||||
-rw-r--r-- | crypto/x509v3/v3_conf.c | 47 | ||||
-rw-r--r-- | crypto/x509v3/v3err.c | 3 | ||||
-rw-r--r-- | crypto/x509v3/x509v3.h | 2 |
11 files changed, 1076 insertions, 29 deletions
diff --git a/apps/asn1pars.c b/apps/asn1pars.c index 8f178db851..dc41da38a0 100644 --- a/apps/asn1pars.c +++ b/apps/asn1pars.c @@ -82,6 +82,8 @@ int MAIN(int, char **); +static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf); + int MAIN(int argc, char **argv) { int i,badops=0,offset=0,ret=1,j; @@ -90,6 +92,7 @@ int MAIN(int argc, char **argv) BIO *in=NULL,*out=NULL,*b64=NULL, *derout = NULL; int informat,indent=0, noout = 0, dump = 0; char *infile=NULL,*str=NULL,*prog,*oidfile=NULL, *derfile=NULL; + char *genstr=NULL, *genconf=NULL; unsigned char *tmpbuf; BUF_MEM *buf=NULL; STACK *osk=NULL; @@ -167,6 +170,16 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; sk_push(osk,*(++argv)); } + else if (strcmp(*argv,"-genstr") == 0) + { + if (--argc < 1) goto bad; + genstr= *(++argv); + } + else if (strcmp(*argv,"-genconf") == 0) + { + if (--argc < 1) goto bad; + genconf= *(++argv); + } else { BIO_printf(bio_err,"unknown option %s\n",*argv); @@ -195,6 +208,8 @@ bad: BIO_printf(bio_err," -strparse offset\n"); BIO_printf(bio_err," a series of these can be used to 'dig' into multiple\n"); BIO_printf(bio_err," ASN1 blob wrappings\n"); + BIO_printf(bio_err," -genstr str string to generate ASN1 structure from\n"); + BIO_printf(bio_err," -genconf file file to generate ASN1 structure from\n"); goto end; } @@ -248,25 +263,39 @@ bad: if ((buf=BUF_MEM_new()) == NULL) goto end; if (!BUF_MEM_grow(buf,BUFSIZ*8)) goto end; /* Pre-allocate :-) */ - if (informat == FORMAT_PEM) + if (genstr || genconf) { - BIO *tmp; - - if ((b64=BIO_new(BIO_f_base64())) == NULL) + num = do_generate(bio_err, genstr, genconf, buf); + if (num < 0) + { + ERR_print_errors(bio_err); goto end; - BIO_push(b64,in); - tmp=in; - in=b64; - b64=tmp; + } } - num=0; - for (;;) + else { - if (!BUF_MEM_grow(buf,(int)num+BUFSIZ)) goto end; - i=BIO_read(in,&(buf->data[num]),BUFSIZ); - if (i <= 0) break; - num+=i; + + if (informat == FORMAT_PEM) + { + BIO *tmp; + + if ((b64=BIO_new(BIO_f_base64())) == NULL) + goto end; + BIO_push(b64,in); + tmp=in; + in=b64; + b64=tmp; + } + + num=0; + for (;;) + { + if (!BUF_MEM_grow(buf,(int)num+BUFSIZ)) goto end; + i=BIO_read(in,&(buf->data[num]),BUFSIZ); + if (i <= 0) break; + num+=i; + } } str=buf->data; @@ -335,3 +364,61 @@ end: EXIT(ret); } +static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) + { + CONF *cnf = NULL; + int len; + long errline; + unsigned char *p; + ASN1_TYPE *atyp = NULL; + + if (genconf) + { + cnf = NCONF_new(NULL); + if (!NCONF_load(cnf, genconf, &errline)) + goto conferr; + if (!genstr) + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (!genstr) + { + BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf); + goto err; + } + } + + atyp = ASN1_generate_nconf(genstr, cnf); + NCONF_free(cnf); + + if (!atyp) + return -1; + + len = i2d_ASN1_TYPE(atyp, NULL); + + if (len <= 0) + goto err; + + if (!BUF_MEM_grow(buf,len)) + goto err; + + p=(unsigned char *)buf->data; + + i2d_ASN1_TYPE(atyp, &p); + + ASN1_TYPE_free(atyp); + return len; + + conferr: + + if (errline > 0) + BIO_printf(bio, "Error on line %ld of config file '%s'\n", + errline, genconf); + else + BIO_printf(bio, "Error loading config file '%s'\n", genconf); + + err: + NCONF_free(cnf); + ASN1_TYPE_free(atyp); + + return -1; + + } diff --git a/crypto/asn1/Makefile.ssl b/crypto/asn1/Makefile.ssl index ae74b50d40..2f1e64dfe8 100644 --- a/crypto/asn1/Makefile.ssl +++ b/crypto/asn1/Makefile.ssl @@ -33,7 +33,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ f_int.c f_string.c n_pkey.c \ f_enum.c a_hdr.c x_pkey.c a_bool.c x_exten.c \ - asn1_par.c asn1_lib.c asn1_err.c a_meth.c a_bytes.c a_strnid.c \ + asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_meth.c a_bytes.c a_strnid.c \ evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ a_print.o a_type.o a_set.o a_dup.o a_d2i_fp.o a_i2d_fp.o \ @@ -45,7 +45,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \ f_int.o f_string.o n_pkey.o \ f_enum.o a_hdr.o x_pkey.o a_bool.o x_exten.o \ - asn1_par.o asn1_lib.o asn1_err.o a_meth.o a_bytes.o a_strnid.o \ + asn1_gen.o asn1_par.o asn1_lib.o asn1_err.o a_meth.o a_bytes.o a_strnid.o \ evp_asn1.o asn_pack.o p5_pbe.o p5_pbev2.o p8_pkey.o asn_moid.o SRC= $(LIBSRC) diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 599cc8bb14..460e0eb6e7 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -949,6 +949,9 @@ int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it void ASN1_add_oid_module(void); +ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf); +ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -962,6 +965,8 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_A2I_ASN1_ENUMERATED 101 #define ASN1_F_A2I_ASN1_INTEGER 102 #define ASN1_F_A2I_ASN1_STRING 103 +#define ASN1_F_APPEND_TAG 177 +#define ASN1_F_ASN1_CB 178 #define ASN1_F_ASN1_CHECK_TLEN 104 #define ASN1_F_ASN1_COLLATE_PRIMITIVE 105 #define ASN1_F_ASN1_COLLECT 106 @@ -972,6 +977,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_ASN1_DUP 111 #define ASN1_F_ASN1_ENUMERATED_SET 112 #define ASN1_F_ASN1_ENUMERATED_TO_BN 113 +#define ASN1_F_ASN1_GENERATE_V3 182 #define ASN1_F_ASN1_GET_OBJECT 114 #define ASN1_F_ASN1_HEADER_NEW 115 #define ASN1_F_ASN1_I2D_BIO 116 @@ -987,6 +993,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_ASN1_SEQ_PACK 126 #define ASN1_F_ASN1_SEQ_UNPACK 127 #define ASN1_F_ASN1_SIGN 128 +#define ASN1_F_ASN1_STR2TYPE 179 #define ASN1_F_ASN1_STRING_TABLE_ADD 129 #define ASN1_F_ASN1_STRING_TYPE_NEW 130 #define ASN1_F_ASN1_TEMPLATE_D2I 131 @@ -996,6 +1003,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 #define ASN1_F_ASN1_UNPACK_STRING 136 #define ASN1_F_ASN1_VERIFY 137 +#define ASN1_F_BITSTR_CB 180 #define ASN1_F_BN_TO_ASN1_ENUMERATED 138 #define ASN1_F_BN_TO_ASN1_INTEGER 139 #define ASN1_F_COLLECT_DATA 140 @@ -1028,6 +1036,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_F_I2D_RSA_PUBKEY 165 #define ASN1_F_LONG_C2I 166 #define ASN1_F_OID_MODULE_INIT 175 +#define ASN1_F_PARSE_TAGGING 181 #define ASN1_F_PKCS5_PBE2_SET 167 #define ASN1_F_X509_CINF_NEW 168 #define ASN1_F_X509_CRL_ADD0_REVOKED 169 @@ -1050,6 +1059,7 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_DATA_IS_WRONG 109 #define ASN1_R_DECODE_ERROR 110 #define ASN1_R_DECODING_ERROR 111 +#define ASN1_R_DEPTH_EXCEEDED 173 #define ASN1_R_ENCODE_ERROR 112 #define ASN1_R_ERROR_LOADING_SECTION 172 #define ASN1_R_ERROR_PARSING_SET_ELEMENT 113 @@ -1063,38 +1073,57 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_FIELD_MISSING 121 #define ASN1_R_FIRST_NUM_TOO_LARGE 122 #define ASN1_R_HEADER_TOO_LONG 123 +#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 174 +#define ASN1_R_ILLEGAL_BOOLEAN 175 #define ASN1_R_ILLEGAL_CHARACTERS 124 +#define ASN1_R_ILLEGAL_FORMAT 176 +#define ASN1_R_ILLEGAL_HEX 177 +#define ASN1_R_ILLEGAL_IMPLICIT_TAG 178 +#define ASN1_R_ILLEGAL_INTEGER 179 +#define ASN1_R_ILLEGAL_NESTED_TAGGING 180 #define ASN1_R_ILLEGAL_NULL 125 +#define ASN1_R_ILLEGAL_NULL_VALUE 181 +#define ASN1_R_ILLEGAL_OBJECT 182 #define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 #define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 #define ASN1_R_ILLEGAL_TAGGED_ANY 127 +#define ASN1_R_ILLEGAL_TIME_VALUE 183 +#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 184 #define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 #define ASN1_R_INVALID_BMPSTRING_LENGTH 129 #define ASN1_R_INVALID_DIGIT 130 +#define ASN1_R_INVALID_MODIFIER 185 +#define ASN1_R_INVALID_NUMBER 186 #define ASN1_R_INVALID_SEPARATOR 131 #define ASN1_R_INVALID_TIME_FORMAT 132 #define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 #define ASN1_R_INVALID_UTF8STRING 134 #define ASN1_R_IV_TOO_LARGE 135 #define ASN1_R_LENGTH_ERROR 136 +#define ASN1_R_LIST_ERROR 187 #define ASN1_R_MISSING_EOC 137 #define ASN1_R_MISSING_SECOND_NUMBER 138 +#define ASN1_R_MISSING_VALUE 188 #define ASN1_R_MSTRING_NOT_UNIVERSAL 139 #define ASN1_R_MSTRING_WRONG_TAG 140 #define ASN1_R_NON_HEX_CHARACTERS 141 +#define ASN1_R_NOT_ASCII_FORMAT 189 #define ASN1_R_NOT_ENOUGH_DATA 142 #define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 #define ASN1_R_NULL_IS_WRONG_LENGTH 144 +#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 190 #define ASN1_R_ODD_NUMBER_OF_CHARS 145 #define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146 #define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 #define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 #define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 195 #define ASN1_R_SHORT_LINE 150 #define ASN1_R_STRING_TOO_LONG 151 #define ASN1_R_STRING_TOO_SHORT 152 #define ASN1_R_TAG_VALUE_TOO_HIGH 153 #define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +#define ASN1_R_TIME_NOT_ASCII_FORMAT 191 #define ASN1_R_TOO_LONG 155 #define ASN1_R_TYPE_NOT_CONSTRUCTED 156 #define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157 @@ -1104,10 +1133,13 @@ void ERR_load_ASN1_strings(void); #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 #define ASN1_R_UNKNOWN_OBJECT_TYPE 162 #define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +#define ASN1_R_UNKNOWN_TAG 192 +#define ASN1_R_UNKOWN_FORMAT 193 #define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 #define ASN1_R_UNSUPPORTED_CIPHER 165 #define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166 #define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +#define ASN1_R_UNSUPPORTED_TYPE 194 #define ASN1_R_WRONG_TAG 168 #define ASN1_R_WRONG_TYPE 169 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index d64f987ac6..55aef5e790 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -70,6 +70,8 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_A2I_ASN1_ENUMERATED,0), "a2i_ASN1_ENUMERATED"}, {ERR_PACK(0,ASN1_F_A2I_ASN1_INTEGER,0), "a2i_ASN1_INTEGER"}, {ERR_PACK(0,ASN1_F_A2I_ASN1_STRING,0), "a2i_ASN1_STRING"}, +{ERR_PACK(0,ASN1_F_APPEND_TAG,0), "APPEND_TAG"}, +{ERR_PACK(0,ASN1_F_ASN1_CB,0), "ASN1_CB"}, {ERR_PACK(0,ASN1_F_ASN1_CHECK_TLEN,0), "ASN1_CHECK_TLEN"}, {ERR_PACK(0,ASN1_F_ASN1_COLLATE_PRIMITIVE,0), "ASN1_COLLATE_PRIMITIVE"}, {ERR_PACK(0,ASN1_F_ASN1_COLLECT,0), "ASN1_COLLECT"}, @@ -80,6 +82,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_DUP,0), "ASN1_dup"}, {ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_SET,0), "ASN1_ENUMERATED_set"}, {ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_TO_BN,0), "ASN1_ENUMERATED_to_BN"}, +{ERR_PACK(0,ASN1_F_ASN1_GENERATE_V3,0), "ASN1_generate_v3"}, {ERR_PACK(0,ASN1_F_ASN1_GET_OBJECT,0), "ASN1_get_object"}, {ERR_PACK(0,ASN1_F_ASN1_HEADER_NEW,0), "ASN1_HEADER_new"}, {ERR_PACK(0,ASN1_F_ASN1_I2D_BIO,0), "ASN1_i2d_bio"}, @@ -95,6 +98,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_SEQ_PACK,0), "ASN1_seq_pack"}, {ERR_PACK(0,ASN1_F_ASN1_SEQ_UNPACK,0), "ASN1_seq_unpack"}, {ERR_PACK(0,ASN1_F_ASN1_SIGN,0), "ASN1_sign"}, +{ERR_PACK(0,ASN1_F_ASN1_STR2TYPE,0), "ASN1_STR2TYPE"}, {ERR_PACK(0,ASN1_F_ASN1_STRING_TABLE_ADD,0), "ASN1_STRING_TABLE_add"}, {ERR_PACK(0,ASN1_F_ASN1_STRING_TYPE_NEW,0), "ASN1_STRING_type_new"}, {ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_D2I,0), "ASN1_TEMPLATE_D2I"}, @@ -104,6 +108,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_OCTETSTRING,0), "ASN1_TYPE_get_octetstring"}, {ERR_PACK(0,ASN1_F_ASN1_UNPACK_STRING,0), "ASN1_unpack_string"}, {ERR_PACK(0,ASN1_F_ASN1_VERIFY,0), "ASN1_verify"}, +{ERR_PACK(0,ASN1_F_BITSTR_CB,0), "BITSTR_CB"}, {ERR_PACK(0,ASN1_F_BN_TO_ASN1_ENUMERATED,0), "BN_to_ASN1_ENUMERATED"}, {ERR_PACK(0,ASN1_F_BN_TO_ASN1_INTEGER,0), "BN_to_ASN1_INTEGER"}, {ERR_PACK(0,ASN1_F_COLLECT_DATA,0), "COLLECT_DATA"}, @@ -136,6 +141,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_I2D_RSA_PUBKEY,0), "i2d_RSA_PUBKEY"}, {ERR_PACK(0,ASN1_F_LONG_C2I,0), "LONG_C2I"}, {ERR_PACK(0,ASN1_F_OID_MODULE_INIT,0), "OID_MODULE_INIT"}, +{ERR_PACK(0,ASN1_F_PARSE_TAGGING,0), "PARSE_TAGGING"}, {ERR_PACK(0,ASN1_F_PKCS5_PBE2_SET,0), "PKCS5_pbe2_set"}, {ERR_PACK(0,ASN1_F_X509_CINF_NEW,0), "X509_CINF_NEW"}, {ERR_PACK(0,ASN1_F_X509_CRL_ADD0_REVOKED,0), "X509_CRL_add0_revoked"}, @@ -161,6 +167,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_DATA_IS_WRONG ,"data is wrong"}, {ASN1_R_DECODE_ERROR ,"decode error"}, {ASN1_R_DECODING_ERROR ,"decoding error"}, +{ASN1_R_DEPTH_EXCEEDED ,"depth exceeded"}, {ASN1_R_ENCODE_ERROR ,"encode error"}, {ASN1_R_ERROR_LOADING_SECTION ,"error loading section"}, {ASN1_R_ERROR_PARSING_SET_ELEMENT ,"error parsing set element"}, @@ -174,38 +181,57 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_FIELD_MISSING ,"field missing"}, {ASN1_R_FIRST_NUM_TOO_LARGE ,"first num too large"}, {ASN1_R_HEADER_TOO_LONG ,"header too long"}, +{ASN1_R_ILLEGAL_BITSTRING_FORMAT ,"illegal bitstring format"}, +{ASN1_R_ILLEGAL_BOOLEAN ,"illegal boolean"}, {ASN1_R_ILLEGAL_CHARACTERS ,"illegal characters"}, +{ASN1_R_ILLEGAL_FORMAT ,"illegal format"}, +{ASN1_R_ILLEGAL_HEX ,"illegal hex"}, +{ASN1_R_ILLEGAL_IMPLICIT_TAG ,"illegal implicit tag"}, +{ASN1_R_ILLEGAL_INTEGER ,"illegal integer"}, +{ASN1_R_ILLEGAL_NESTED_TAGGING ,"illegal nested tagging"}, {ASN1_R_ILLEGAL_NULL ,"illegal null"}, +{ASN1_R_ILLEGAL_NULL_VALUE ,"illegal null value"}, +{ASN1_R_ILLEGAL_OBJECT ,"illegal object"}, {ASN1_R_ILLEGAL_OPTIONAL_ANY ,"illegal optional any"}, {ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE ,"illegal options on item template"}, {ASN1_R_ILLEGAL_TAGGED_ANY ,"illegal tagged any"}, +{ASN1_R_ILLEGAL_TIME_VALUE ,"illegal time value"}, +{ASN1_R_INTEGER_NOT_ASCII_FORMAT ,"integer not ascii format"}, {ASN1_R_INTEGER_TOO_LARGE_FOR_LONG ,"integer too large for long"}, {ASN1_R_INVALID_BMPSTRING_LENGTH ,"invalid bmpstring length"}, {ASN1_R_INVALID_DIGIT ,"invalid digit"}, +{ASN1_R_INVALID_MODIFIER ,"invalid modifier"}, +{ASN1_R_INVALID_NUMBER ,"invalid number"}, {ASN1_R_INVALID_SEPARATOR ,"invalid separator"}, {ASN1_R_INVALID_TIME_FORMAT ,"invalid time format"}, {ASN1_R_INVALID_UNIVERSALSTRING_LENGTH ,"invalid universalstring length"}, {ASN1_R_INVALID_UTF8STRING ,"invalid utf8string"}, {ASN1_R_IV_TOO_LARGE ,"iv too large"}, {ASN1_R_LENGTH_ERROR ,"length error"}, +{ASN1_R_LIST_ERROR ,"list error"}, {ASN1_R_MISSING_EOC ,"missing eoc"}, {ASN1_R_MISSING_SECOND_NUMBER ,"missing second number"}, +{ASN1_R_MISSING_VALUE ,"missing value"}, {ASN1_R_MSTRING_NOT_UNIVERSAL ,"mstring not universal"}, {ASN1_R_MSTRING_WRONG_TAG ,"mstring wrong tag"}, {ASN1_R_NON_HEX_CHARACTERS ,"non hex characters"}, +{ASN1_R_NOT_ASCII_FORMAT ,"not ascii format"}, {ASN1_R_NOT_ENOUGH_DATA ,"not enough data"}, {ASN1_R_NO_MATCHING_CHOICE_TYPE ,"no matching choice type"}, {ASN1_R_NULL_IS_WRONG_LENGTH ,"null is wrong length"}, +{ASN1_R_OBJECT_NOT_ASCII_FORMAT ,"object not ascii format"}, {ASN1_R_ODD_NUMBER_OF_CHARS ,"odd number of chars"}, {ASN1_R_PRIVATE_KEY_HEADER_MISSING ,"private key header missing"}, {ASN1_R_SECOND_NUMBER_TOO_LARGE ,"second number too large"}, {ASN1_R_SEQUENCE_LENGTH_MISMATCH ,"sequence length mismatch"}, {ASN1_R_SEQUENCE_NOT_CONSTRUCTED ,"sequence not constructed"}, +{ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG ,"sequence or set needs config"}, {ASN1_R_SHORT_LINE ,"short line"}, {ASN1_R_STRING_TOO_LONG ,"string too long"}, {ASN1_R_STRING_TOO_SHORT ,"string too short"}, {ASN1_R_TAG_VALUE_TOO_HIGH ,"tag value too high"}, {ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD,"the asn1 object identifier is not known for this md"}, +{ASN1_R_TIME_NOT_ASCII_FORMAT ,"time not ascii format"}, {ASN1_R_TOO_LONG ,"too long"}, {ASN1_R_TYPE_NOT_CONSTRUCTED ,"type not constructed"}, {ASN1_R_UNABLE_TO_DECODE_RSA_KEY ,"unable to decode rsa key"}, @@ -215,10 +241,13 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM ,"unknown message digest algorithm"}, {ASN1_R_UNKNOWN_OBJECT_TYPE ,"unknown object type"}, {ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE ,"unknown public key type"}, +{ASN1_R_UNKNOWN_TAG ,"unknown tag"}, +{ASN1_R_UNKOWN_FORMAT ,"unkown format"}, {ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE ,"unsupported any defined by type"}, {ASN1_R_UNSUPPORTED_CIPHER ,"unsupported cipher"}, {ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM ,"unsupported encryption algorithm"}, {ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE ,"unsupported public key type"}, +{ASN1_R_UNSUPPORTED_TYPE ,"unsupported type"}, {ASN1_R_WRONG_TAG ,"wrong tag"}, {ASN1_R_WRONG_TYPE ,"wrong type"}, {0,NULL} diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c new file mode 100644 index 0000000000..d6f7c9b31e --- /dev/null +++ b/crypto/asn1/asn1_gen.c @@ -0,0 +1,831 @@ +/* asn1_gen.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2002. + */ +/* ==================================================================== + * Copyright (c) 2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include "cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/x509v3.h> + +#define ASN1_GEN_FLAG 0x10000 +#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1) +#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2) +#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3) +#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4) +#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5) +#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6) +#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|7) + +#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val} + +#define ASN1_FLAG_EXP_MAX 20 + +/* Input formats */ + +/* ASCII: default */ +#define ASN1_GEN_FORMAT_ASCII 1 +/* UTF8 */ +#define ASN1_GEN_FORMAT_UTF8 2 +/* Hex */ +#define ASN1_GEN_FORMAT_HEX 3 +/* List of bits */ +#define ASN1_GEN_FORMAT_BITLIST 4 + + +struct tag_name_st + { + char *strnam; + int len; + int tag; + }; + +typedef struct + { + int exp_tag; + int exp_class; + int exp_constructed; + int exp_pad; + long exp_len; + } tag_exp_type; + +typedef struct + { + int imp_tag; + int imp_class; + int utype; + int format; + const char *str; + tag_exp_type exp_list[ASN1_FLAG_EXP_MAX]; + int exp_count; + } tag_exp_arg; + +static int bitstr_cb(const char *elem, int len, void *bitstr); +static int asn1_cb(const char *elem, int len, void *bitstr); +static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok); +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass); +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf); +static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype); +static int asn1_str2tag(const char *tagstr, int len); + +ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf) + { + X509V3_CTX cnf; + + if (!nconf) + return ASN1_generate_v3(str, NULL); + + X509V3_set_nconf(&cnf, nconf); + return ASN1_generate_v3(str, &cnf); + } + +ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf) + { + ASN1_TYPE *ret; + tag_exp_arg asn1_tags; + tag_exp_type *etmp; + + int i, len; + + unsigned char *orig_der = NULL, *new_der = NULL; + unsigned char *cpy_start, *p; + int cpy_len; + long hdr_len; + int hdr_constructed, hdr_tag, hdr_class; + int r; + + asn1_tags.imp_tag = -1; + asn1_tags.imp_class = -1; + asn1_tags.format = ASN1_GEN_FORMAT_ASCII; + asn1_tags.exp_count = 0; + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) + return NULL; + + if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET)) + { + if (!cnf) + { + ASN1err(ASN1_F_ASN1_GENERATE_V3, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG); + return NULL; + } + ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf); + } + else + ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); + + if (!ret) + return NULL; + + /* If no tagging return base type */ + if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0)) + return ret; + + /* Generate the encoding */ + cpy_len = i2d_ASN1_TYPE(ret, &orig_der); + ASN1_TYPE_free(ret); + ret = NULL; + /* Set point to start copying for modified encoding */ + cpy_start = orig_der; + + /* Do we need IMPLICIT tagging? */ + if (asn1_tags.imp_tag != -1) + { + /* If IMPLICIT we will replace the underlying tag */ + /* Skip existing tag+len */ + r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len); + if (r & 0x80) + goto err; + /* Update copy length */ + cpy_len -= cpy_start - orig_der; + /* For IMPLICIT tagging the length should match the + * original length and constructed flag should be + * consistent. + */ + if (r & 0x1) + { + /* Indefinite length constructed */ + hdr_constructed = 2; + hdr_len = 0; + } + else + /* Just retain constructed flag */ + hdr_constructed = r & V_ASN1_CONSTRUCTED; + /* Work out new length with IMPLICIT tag: ignore constructed + * because it will mess up if indefinite length + */ + len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag); + } + else + len = cpy_len; + + /* Work out length in any EXPLICIT, starting from end */ + + for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--) + { + /* Content length: number of content octets + any padding */ + len += etmp->exp_pad; + etmp->exp_len = len; + /* Total object length: length including new header */ + len = ASN1_object_size(0, len, etmp->exp_tag); + } + + /* Allocate buffer for new encoding */ + + new_der = OPENSSL_malloc(len); + + /* Generate tagged encoding */ + + p = new_der; + + /* Output explicit tags first */ + + for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++) + { + ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len, + etmp->exp_tag, etmp->exp_class); + if (etmp->exp_pad) + *p++ = 0; + } + + /* If IMPLICIT, output tag */ + + if (asn1_tags.imp_tag != -1) + ASN1_put_object(&p, hdr_constructed, hdr_len, + asn1_tags.imp_tag, asn1_tags.imp_class); + + /* Copy across original encoding */ + memcpy(p, cpy_start, cpy_len); + + p = new_der; + + /* Obtain new ASN1_TYPE structure */ + ret = d2i_ASN1_TYPE(NULL, &p, len); + + err: + if (orig_der) + OPENSSL_free(orig_der); + if (new_der) + OPENSSL_free(new_der); + + return ret; + + } + +static int asn1_cb(const char *elem, int len, void *bitstr) + { + tag_exp_arg *arg = bitstr; + int i; + int utype; + int vlen; + const char *p, *vstart = NULL; + + int tmp_tag, tmp_class; + + for(i = 0, p = elem; i < len; p++, i++) + { + /* Look for the ':' in name value pairs */ + if (*p == ':') + { + vstart = p + 1; + vlen = len - (vstart - elem); + len = p - elem; + break; + } + } + + utype = asn1_str2tag(elem, len); + + if (utype == -1) + { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG); + ERR_add_error_data(2, "tag=", elem); + return -1; + } + + /* If this is not a modifier mark end of string and exit */ + if (!(utype & ASN1_GEN_FLAG)) + { + arg->utype = utype; + arg->str = vstart; + /* If no value and not end of string, error */ + if (!vstart && elem[len]) + { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE); + return -1; + } + return 0; + } + + switch(utype) + { + + case ASN1_GEN_FLAG_IMP: + /* Check for illegal multiple IMPLICIT tagging */ + if (arg->imp_tag != -1) + { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING); + return -1; + } + if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class)) + return -1; + break; + + case ASN1_GEN_FLAG_EXP: + + if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class)) + return -1; + if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0)) + return -1; + break; + + case ASN1_GEN_FLAG_SEQWRAP: + if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_BITWRAP: + if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_OCTWRAP: + if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1)) + return -1; + break; + + case ASN1_GEN_FLAG_FORMAT: + if (!strncmp(vstart, "ASCII", 5)) + arg->format = ASN1_GEN_FORMAT_ASCII; + else if (!strncmp(vstart, "UTF8", 4)) + arg->format = ASN1_GEN_FORMAT_UTF8; + else if (!strncmp(vstart, "HEX", 3)) + arg->format = ASN1_GEN_FORMAT_HEX; + else if (!strncmp(vstart, "BITLIST", 3)) + arg->format = ASN1_GEN_FORMAT_BITLIST; + else + { + ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKOWN_FORMAT); + return -1; + } + break; + + } + + return 1; + + } + +static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) + { + char erch[2]; + long tag_num; + char *eptr; + if (!vstart) + return 0; + tag_num = strtoul(vstart, &eptr, 10); + /* Check we haven't gone past max length: should be impossible */ + if (eptr && *eptr && (eptr > vstart + vlen)) + return 0; + if (tag_num < 0) + { + ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER); + return 0; + } + *ptag = tag_num; + /* If we have non numeric characters, parse them */ + if (eptr) + vlen -= eptr - vstart; + else + vlen = 0; + if (vlen) + { + switch (*eptr) + { + + case 'U': + *pclass = V_ASN1_UNIVERSAL; + break; + + case 'A': + *pclass = V_ASN1_APPLICATION; + break; + + case 'P': + *pclass = V_ASN1_PRIVATE; + break; + + case 'C': + *pclass = V_ASN1_CONTEXT_SPECIFIC; + break; + + default: + erch[0] = *eptr; + erch[1] = 0; + ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER); + ERR_add_error_data(2, "Char=", erch); + return 0; + break; + + } + } + else + *pclass = V_ASN1_CONTEXT_SPECIFIC; + + return 1; + + } + +/* Handle multiple types: SET and SEQUENCE */ + +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) + { + ASN1_TYPE *ret = NULL, *typ = NULL; + STACK_OF(ASN1_TYPE) *sk = NULL; + STACK_OF(CONF_VALUE) *sect = NULL; + unsigned char *der = NULL, *p; + int derlen; + int i, is_set; + sk = sk_ASN1_TYPE_new_null(); + if (section) + { + if (!cnf) + goto bad; + sect = X509V3_get_section(cnf, (char *)section); + if (!sect) + goto bad; + for (i = 0; i < sk_CONF_VALUE_num(sect); i++) + { + typ = ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf); + if (!typ) + goto bad; + sk_ASN1_TYPE_push(sk, typ); + typ = NULL; + } + } + + /* Now we has a STACK of the components, convert to the correct form */ + + if (utype == V_ASN1_SET) + is_set = 1; + else + is_set = 0; + + + derlen = i2d_ASN1_SET((STACK *)sk, NULL, i2d_ASN1_TYPE, utype, V_ASN1_UNIVERSAL, is_set); + der = OPENSSL_malloc(derlen); + p = der; + i2d_ASN1_SET((STACK *)sk, &p, i2d_ASN1_TYPE, utype, V_ASN1_UNIVERSAL, is_set); + + if (!(ret = ASN1_TYPE_new())) + goto bad; + + if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype))) + goto bad; + + ret->type = utype; + + ret->value.asn1_string->data = der; + ret->value.asn1_string->length = derlen; + + der = NULL; + + bad: + + if (der) + OPENSSL_free(der); + + if (sk) + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + if (typ) + ASN1_TYPE_free(typ); + if (sect) + X509V3_section_free(cnf, sect); + |