Initial ASN1 generation code. This can construct
arbitrary encodings from strings and config files.

Documentation to follow...
diff --git a/apps/asn1pars.c b/apps/asn1pars.c
index 8f178db..dc41da3 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 @@
 	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 @@
 			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 @@
 		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 @@
 	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 @@
 	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 ae74b50..2f1e64d 100644
--- a/crypto/asn1/Makefile.ssl
+++ b/crypto/asn1/Makefile.ssl
@@ -33,7 +33,7 @@
 	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 @@
 	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 599cc8b..460e0eb 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -949,6 +949,9 @@
 
 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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 @@
 #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 d64f987..55aef5e 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -70,6 +70,8 @@
 {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 @@
 {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 @@
 {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 @@
 {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 @@
 {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 @@
 {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 @@
 {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 @@
 {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 0000000..d6f7c9b
--- /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);
+
+	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;
+	}
+
diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h
index f467144..48695a0 100644
--- a/crypto/conf/conf.h
+++ b/crypto/conf/conf.h
@@ -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_IMODULE)
 
 struct conf_st;
-typedef struct conf_st CONF;
 struct conf_method_st;
 typedef struct conf_method_st CONF_METHOD;
 
diff --git a/crypto/ossl_typ.h b/crypto/ossl_typ.h
index 6bd42ae..420d5e6 100644
--- a/crypto/ossl_typ.h
+++ b/crypto/ossl_typ.h
@@ -111,6 +111,9 @@
 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 */
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
index 0e9e7dc..baa9ca1 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509v3/v3_alt.c
@@ -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_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 @@
 			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 @@
 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;
+	}
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
index 1a3448e..372c65d 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509v3/v3_conf.c
@@ -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
@@ -69,11 +69,12 @@
 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 *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 @@
 	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 @@
 /* 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 @@
 		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 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.
diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c
index 6458e95..3cb543e 100644
--- a/crypto/x509v3/v3err.c
+++ b/crypto/x509v3/v3err.c
@@ -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 @@
 {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"},
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index daecc55..e1334b4 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -132,7 +132,6 @@
 };
 
 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 @@
 #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