Initial ASN1 generation code. This can construct
authorDr. Stephen Henson <steve@openssl.org>
Tue, 12 Nov 2002 13:34:51 +0000 (13:34 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 12 Nov 2002 13:34:51 +0000 (13:34 +0000)
arbitrary encodings from strings and config files.

Documentation to follow...

apps/asn1pars.c
crypto/asn1/Makefile.ssl
crypto/asn1/asn1.h
crypto/asn1/asn1_err.c
crypto/asn1/asn1_gen.c [new file with mode: 0644]
crypto/conf/conf.h
crypto/ossl_typ.h
crypto/x509v3/v3_alt.c
crypto/x509v3/v3_conf.c
crypto/x509v3/v3err.c
crypto/x509v3/x509v3.h

index 8f178db..dc41da3 100644 (file)
@@ -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;
+
+       }
index ae74b50..2f1e64d 100644 (file)
@@ -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)
index 599cc8b..460e0eb 100644 (file)
@@ -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
 
index d64f987..55aef5e 100644 (file)
@@ -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 (file)
index 0000000..d6f7c9b
--- /dev/null
@@ -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);
+
+       return ret;
+       }
+
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok)
+       {
+       tag_exp_type *exp_tmp;
+       /* Can only have IMPLICIT if permitted */
+       if ((arg->imp_tag != -1) && !imp_ok)
+               {
+               ASN1err(ASN1_F_APPEND_TAG, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+               return 0;
+               }
+
+       if (arg->exp_count == ASN1_FLAG_EXP_MAX)
+               {
+               ASN1err(ASN1_F_APPEND_TAG, ASN1_R_DEPTH_EXCEEDED);
+               return 0;
+               }
+
+       exp_tmp = &arg->exp_list[arg->exp_count++];
+
+       /* If IMPLICIT set tag to implicit value then
+        * reset implicit tag since it has been used.
+        */
+       if (arg->imp_tag != -1)
+               {
+               exp_tmp->exp_tag = arg->imp_tag;
+               exp_tmp->exp_class = arg->imp_class;
+               arg->imp_tag = -1;
+               arg->imp_class = -1;
+               }
+       else
+               {
+               exp_tmp->exp_tag = exp_tag;
+               exp_tmp->exp_class = exp_class;
+               }
+       exp_tmp->exp_constructed = exp_constructed;
+       exp_tmp->exp_pad = exp_pad;
+
+       return 1;
+       }
+
+
+static int asn1_str2tag(const char *tagstr, int len)
+       {
+       int i;
+       static struct tag_name_st *tntmp, tnst [] = {
+               ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
+               ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
+               ASN1_GEN_STR("NULL", V_ASN1_NULL),
+               ASN1_GEN_STR("INT", V_ASN1_INTEGER),
+               ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
+               ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
+               ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
+               ASN1_GEN_STR("OID", V_ASN1_OBJECT),
+               ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
+               ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
+               ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
+               ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
+               ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
+               ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
+               ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
+               ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
+               ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
+               ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
+               ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
+               ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
+               ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
+               ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
+               ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
+               ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
+               ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
+               ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
+               ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
+               ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
+               ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
+               ASN1_GEN_STR("T61", V_ASN1_T61STRING),
+               ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
+               ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
+
+               /* Special cases */
+               ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
+               ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
+               ASN1_GEN_STR("SET", V_ASN1_SET),
+               /* type modifiers */
+               /* Explicit tag */
+               ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
+               ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
+               /* Implicit tag */
+               ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
+               ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
+               /* OCTET STRING wrapper */
+               ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
+               /* SEQUENCE wrapper */
+               ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
+               /* BIT STRING wrapper */
+               ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
+               ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
+               ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
+       };
+
+       if (len == -1)
+               len = strlen(tagstr);
+       
+       tntmp = tnst;   
+       for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++)
+               {
+               if (!strncmp(tntmp->strnam, tagstr, tntmp->len))
+                       return tntmp->tag;
+               }
+       
+       return -1;
+       }
+
+static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
+       {
+       ASN1_TYPE *atmp = NULL;
+
+       CONF_VALUE vtmp;
+
+       unsigned char *rdata;
+       long rdlen;
+
+       int no_unused = 1;
+
+       if (!(atmp = ASN1_TYPE_new()))
+               {
+               ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+               return NULL;
+               }
+
+       if (!str)
+               str = "";
+
+       switch(utype)
+               {
+
+               case V_ASN1_NULL:
+               if (str && *str)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE);
+                       goto bad_form;
+                       }
+               break;
+               
+               case V_ASN1_BOOLEAN:
+               if (format != ASN1_GEN_FORMAT_ASCII)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT);
+                       goto bad_form;
+                       }
+               vtmp.value = (char *)str;
+               if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN);
+                       goto bad_str;
+                       }
+               break;
+
+               case V_ASN1_INTEGER:
+               case V_ASN1_ENUMERATED:
+               if (format != ASN1_GEN_FORMAT_ASCII)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+                       goto bad_form;
+                       }
+               if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
+                       goto bad_str;
+                       }
+               break;
+
+               case V_ASN1_OBJECT:
+               if (format != ASN1_GEN_FORMAT_ASCII)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+                       goto bad_form;
+                       }
+               if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
+                       goto bad_str;
+                       }
+               break;
+
+               case V_ASN1_UTCTIME:
+               case V_ASN1_GENERALIZEDTIME:
+               if (format != ASN1_GEN_FORMAT_ASCII)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
+                       goto bad_form;
+                       }
+               if (!(atmp->value.asn1_string = ASN1_STRING_new()))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+                       goto bad_str;
+                       }
+               if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+                       goto bad_str;
+                       }
+               atmp->value.asn1_string->type = utype;
+               if (!ASN1_TIME_check(atmp->value.asn1_string))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE);
+                       goto bad_str;
+                       }
+
+               break;
+
+               case V_ASN1_BMPSTRING:
+               case V_ASN1_PRINTABLESTRING:
+               case V_ASN1_IA5STRING:
+               case V_ASN1_T61STRING:
+               case V_ASN1_UTF8STRING:
+               case V_ASN1_VISIBLESTRING:
+               case V_ASN1_UNIVERSALSTRING:
+
+               if (format == ASN1_GEN_FORMAT_ASCII)
+                       format = MBSTRING_ASC;
+               else if (format == ASN1_GEN_FORMAT_UTF8)
+                       format = MBSTRING_UTF8;
+               else
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT);
+                       goto bad_form;
+                       }
+
+
+               if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
+                                               -1, format, ASN1_tag2bit(utype)) <= 0)
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+                       goto bad_str;
+                       }
+               
+
+               break;
+
+               case V_ASN1_BIT_STRING:
+
+               case V_ASN1_OCTET_STRING:
+
+               if (!(atmp->value.asn1_string = ASN1_STRING_new()))
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+                       goto bad_form;
+                       }
+
+               if (format == ASN1_GEN_FORMAT_HEX)
+                       {
+
+                       if (!(rdata = string_to_hex((char *)str, &rdlen)))
+                               {
+                               ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
+                               goto bad_str;
+                               }
+
+                       atmp->value.asn1_string->data = rdata;
+                       atmp->value.asn1_string->length = rdlen;
+                       atmp->value.asn1_string->type = utype;
+
+                       }
+               else if (format == ASN1_GEN_FORMAT_ASCII)
+                       ASN1_STRING_set(atmp->value.asn1_string, str, -1);
+               else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING))
+                       {
+                       if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
+                               {
+                               ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR);
+                               goto bad_str;
+                               }
+                       no_unused = 0;
+                       
+                       }
+               else 
+                       {
+                       ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+                       goto bad_form;
+                       }
+
+               if ((utype == V_ASN1_BIT_STRING) && no_unused)
+                       {
+                       atmp->value.asn1_string->flags
+                               &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+                       atmp->value.asn1_string->flags
+                               |= ASN1_STRING_FLAG_BITS_LEFT;
+                       }
+
+
+               break;
+
+               default:
+               ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE);
+               goto bad_str;
+               break;
+               }
+
+
+       atmp->type = utype;
+       return atmp;
+
+
+       bad_str:
+       ERR_add_error_data(2, "string=", str);
+       bad_form:
+
+       ASN1_TYPE_free(atmp);
+       return NULL;
+
+       }
+
+static int bitstr_cb(const char *elem, int len, void *bitstr)
+       {
+       long bitnum;
+       char *eptr;
+       if (!elem)
+               return 0;
+       bitnum = strtoul(elem, &eptr, 10);
+       if (eptr && *eptr && (eptr != elem + len))
+               return 0;
+       if (bitnum < 0)
+               {
+               ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER);
+               return 0;
+               }
+       if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
+               {
+               ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE);
+               return 0;
+               }
+       return 1;
+       }
+
index f467144..48695a0 100644 (file)
@@ -65,6 +65,8 @@
 #include <openssl/safestack.h>
 #include <openssl/e_os2.h>
 
+#include <openssl/ossl_typ.h>
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -81,7 +83,6 @@ DECLARE_STACK_OF(CONF_MODULE)
 DECLARE_STACK_OF(CONF_IMODULE)
 
 struct conf_st;
-typedef struct conf_st CONF;
 struct conf_method_st;
 typedef struct conf_method_st CONF_METHOD;
 
index 6bd42ae..420d5e6 100644 (file)
@@ -111,6 +111,9 @@ typedef struct X509_name_st X509_NAME;
 typedef struct x509_store_st X509_STORE;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
 
+typedef struct v3_ext_ctx X509V3_CTX;
+typedef struct conf_st CONF;
+
 typedef struct engine_st ENGINE;
 
   /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */
index 0e9e7dc..baa9ca1 100644 (file)
@@ -3,7 +3,7 @@
  * project 1999.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-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
@@ -65,6 +65,8 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx
 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
+static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
+
 X509V3_EXT_METHOD v3_alt[] = {
 { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
 0,0,0,0,
@@ -432,6 +434,13 @@ if(!name_cmp(name, "email")) {
                        goto err;
        }
        type = GEN_IPADD;
+} else if(!name_cmp(name, "otherName")) {
+       if (!do_othername(gen, value, ctx))
+               {
+               X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_OTHERNAME_ERROR);
+               goto err;
+               }
+       type = GEN_OTHERNAME;
 } else {
        X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
        ERR_add_error_data(2, "name=", name);
@@ -455,3 +464,28 @@ err:
 GENERAL_NAME_free(gen);
 return NULL;
 }
+
+static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
+       {
+       char *objtmp = NULL, *p;
+       int objlen;
+       if (!(p = strchr(value, ';')))
+               return 0;
+       if (!(gen->d.otherName = OTHERNAME_new()))
+               return 0;
+       /* Free this up because we will overwrite it.
+        * no need to free type_id because it is static
+        */
+       ASN1_TYPE_free(gen->d.otherName->value);
+       if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
+               return 0;
+       objlen = p - value;
+       objtmp = OPENSSL_malloc(objlen + 1);
+       strncpy(objtmp, value, objlen);
+       objtmp[objlen] = 0;
+       gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
+       OPENSSL_free(objtmp);   
+       if (!gen->d.otherName->type_id)
+               return 0;
+       return 1;
+       }
index 1a3448e..372c65d 100644 (file)
@@ -3,7 +3,7 @@
  * project 1999.
  */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-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
 static int v3_check_critical(char **value);
 static int v3_check_generic(char **value);
 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value);
-static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type);
+static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type, X509V3_CTX *ctx);
 static char *conf_lhash_get_string(void *db, char *section, char *value);
 static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, char *section);
 static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid,
                                                 int crit, void *ext_struc);
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len);
 /* CONF *conf:  Config file    */
 /* char *name:  Name    */
 /* char *value:  Value    */
@@ -85,7 +86,7 @@ X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
        X509_EXTENSION *ret;
        crit = v3_check_critical(&value);
        if ((ext_type = v3_check_generic(&value))) 
-               return v3_generic_extension(name, value, crit, ext_type);
+               return v3_generic_extension(name, value, crit, ext_type, ctx);
        ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
        if (!ret)
                {
@@ -105,7 +106,7 @@ X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
        crit = v3_check_critical(&value);
        if ((ext_type = v3_check_generic(&value))) 
                return v3_generic_extension(OBJ_nid2sn(ext_nid),
-                                                        value, crit, ext_type);
+                                                value, crit, ext_type, ctx);
        return do_ext_nconf(conf, ctx, ext_nid, crit, value);
        }
 
@@ -235,17 +236,29 @@ static int v3_check_critical(char **value)
 /* Check extension string for generic extension and return the type */
 static int v3_check_generic(char **value)
 {
+       int gen_type = 0;
        char *p = *value;
-       if ((strlen(p) < 4) || strncmp(p, "DER:,", 4)) return 0;
-       p+=4;
+       if ((strlen(p) >= 4) && !strncmp(p, "DER:,", 4))
+               {
+               p+=4;
+               gen_type = 1;
+               }
+       if ((strlen(p) >= 5) && !strncmp(p, "ASN1:,", 5))
+               {
+               p+=5;
+               gen_type = 2;
+               }
+       else
+               return 0;
+
        while (isspace((unsigned char)*p)) p++;
        *value = p;
-       return 1;
+       return gen_type;
 }
 
 /* Create a generic extension: for now just handle DER type */
 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
-            int crit, int type)
+            int crit, int gen_type, X509V3_CTX *ctx)
        {
        unsigned char *ext_der=NULL;
        long ext_len;
@@ -259,7 +272,12 @@ static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
                goto err;
                }
 
-       if (!(ext_der = string_to_hex(value, &ext_len)))
+       if (gen_type == 1)
+               ext_der = string_to_hex(value, &ext_len);
+       else if (gen_type == 2)
+               ext_der = generic_asn1(value, ctx, &ext_len);
+
+       if (ext_der == NULL)
                {
                X509V3err(X509V3_F_V3_GENERIC_EXTENSION,X509V3_R_EXTENSION_VALUE_ERROR);
                ERR_add_error_data(2, "value=", value);
@@ -286,6 +304,17 @@ static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
 
        }
 
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len)
+       {
+       ASN1_TYPE *typ;
+       unsigned char *ext_der = NULL;
+       typ = ASN1_generate_v3(value, ctx);
+       if (typ == NULL)
+               return NULL;
+       *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
+       ASN1_TYPE_free(typ);
+       return ext_der;
+       }
 
 /* This is the main function: add a bunch of extensions based on a config file
  * section to an extension STACK.
index 6458e95..3cb543e 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/x509v3/v3err.c */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-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
@@ -152,6 +152,7 @@ static ERR_STRING_DATA X509V3_str_reasons[]=
 {X509V3_R_NO_PUBLIC_KEY                  ,"no public key"},
 {X509V3_R_NO_SUBJECT_DETAILS             ,"no subject details"},
 {X509V3_R_ODD_NUMBER_OF_DIGITS           ,"odd number of digits"},
+{X509V3_R_OTHERNAME_ERROR                ,"othername error"},
 {X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS   ,"unable to get issuer details"},
 {X509V3_R_UNABLE_TO_GET_ISSUER_KEYID     ,"unable to get issuer keyid"},
 {X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT    ,"unknown bit string argument"},
index daecc55..e1334b4 100644 (file)
@@ -132,7 +132,6 @@ void *db;
 };
 
 typedef struct v3_ext_method X509V3_EXT_METHOD;
-typedef struct v3_ext_ctx X509V3_CTX;
 
 DECLARE_STACK_OF(X509V3_EXT_METHOD)
 
@@ -640,6 +639,7 @@ void ERR_load_X509V3_strings(void);
 #define X509V3_R_NO_PUBLIC_KEY                          114
 #define X509V3_R_NO_SUBJECT_DETAILS                     125
 #define X509V3_R_ODD_NUMBER_OF_DIGITS                   112
+#define X509V3_R_OTHERNAME_ERROR                        147
 #define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS           122
 #define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID             123
 #define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT            111