diff options
author | steve <steve> | 2000-11-11 01:18:07 +0000 |
---|---|---|
committer | steve <steve> | 2000-11-11 01:18:07 +0000 |
commit | 8e8e1737354d506e1a1ebe2dc5b7dd3ce3f28060 (patch) | |
tree | 69a3f060f251c0b24faf8a10b4038d8156556244 | |
parent | 2fad3fbce91fef85425fba110cfc5beda8fd8c0b (diff) | |
download | openssl-8e8e1737354d506e1a1ebe2dc5b7dd3ce3f28060.tar.gz |
Initial new ASN1 template code. This is highly
experimental, doesn't work properly and does
lots of evil things. Quite a few of the files
aren't even compile in yet.
It should however give a rough idea of how
things will ultimately work.
Don't even think about modifying any of this yet...
-rw-r--r-- | crypto/asn1/Makefile.ssl | 42 | ||||
-rw-r--r-- | crypto/asn1/a_bytes.c | 6 | ||||
-rw-r--r-- | crypto/asn1/asn1.h | 95 | ||||
-rw-r--r-- | crypto/asn1/asn1_err.c | 51 | ||||
-rw-r--r-- | crypto/asn1/asn1t.h | 512 | ||||
-rw-r--r-- | crypto/asn1/tasn_dec.c | 810 | ||||
-rw-r--r-- | crypto/asn1/tasn_enc.c | 415 | ||||
-rw-r--r-- | crypto/asn1/tasn_fre.c | 152 | ||||
-rw-r--r-- | crypto/asn1/tasn_new.c | 187 | ||||
-rw-r--r-- | crypto/asn1/tasn_prn.c | 196 | ||||
-rw-r--r-- | crypto/asn1/tasn_typ.c | 84 | ||||
-rw-r--r-- | crypto/asn1/tasn_utl.c | 185 |
12 files changed, 2673 insertions, 62 deletions
diff --git a/crypto/asn1/Makefile.ssl b/crypto/asn1/Makefile.ssl index cb73cda47..ae8f6470d 100644 --- a/crypto/asn1/Makefile.ssl +++ b/crypto/asn1/Makefile.ssl @@ -31,6 +31,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ d2i_s_pr.c i2d_s_pr.c d2i_s_pu.c i2d_s_pu.c \ d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ t_req.c t_x509.c t_x509a.c t_crl.c t_pkey.c t_spki.c t_bitst.c \ + tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ p7_i_s.c p7_signi.c p7_signd.c p7_recip.c p7_enc_c.c p7_evp.c \ p7_dgst.c p7_s_e.c p7_enc.c p7_lib.c \ f_int.c f_string.c i2d_dhp.c i2d_dsap.c d2i_dhp.c d2i_dsap.c n_pkey.c \ @@ -46,6 +47,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ d2i_s_pr.o i2d_s_pr.o d2i_s_pu.o i2d_s_pu.o \ d2i_pu.o d2i_pr.o i2d_pu.o i2d_pr.o \ t_req.o t_x509.o t_x509a.o t_crl.o t_pkey.o t_spki.o t_bitst.o \ + tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \ p7_i_s.o p7_signi.o p7_signd.o p7_recip.o p7_enc_c.o p7_evp.o \ p7_dgst.o p7_s_e.o p7_enc.o p7_lib.o \ f_int.o f_string.o i2d_dhp.o i2d_dsap.o d2i_dhp.o d2i_dsap.o n_pkey.o \ @@ -55,7 +57,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \ SRC= $(LIBSRC) -EXHEADER= asn1.h asn1_mac.h +EXHEADER= asn1.h asn1_mac.h asn1t.h HEADER= $(EXHEADER) ALL= $(GENERAL) $(SRC) $(HEADER) @@ -1097,6 +1099,44 @@ t_x509a.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h t_x509a.o: ../../include/openssl/sha.h ../../include/openssl/stack.h t_x509a.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h t_x509a.o: ../../include/openssl/x509_vfy.h ../cryptlib.h +tasn_dec.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_dec.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_dec.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h +tasn_dec.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +tasn_dec.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h +tasn_dec.o: ../../include/openssl/opensslconf.h +tasn_dec.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_dec.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +tasn_enc.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_enc.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_enc.o: ../../include/openssl/crypto.h ../../include/openssl/obj_mac.h +tasn_enc.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +tasn_enc.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_enc.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +tasn_fre.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_fre.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_fre.o: ../../include/openssl/crypto.h ../../include/openssl/obj_mac.h +tasn_fre.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +tasn_fre.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_fre.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +tasn_new.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_new.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_new.o: ../../include/openssl/crypto.h ../../include/openssl/err.h +tasn_new.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h +tasn_new.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +tasn_new.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_new.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +tasn_typ.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_typ.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_typ.o: ../../include/openssl/crypto.h ../../include/openssl/opensslconf.h +tasn_typ.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_typ.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +tasn_utl.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +tasn_utl.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +tasn_utl.o: ../../include/openssl/crypto.h ../../include/openssl/obj_mac.h +tasn_utl.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h +tasn_utl.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +tasn_utl.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h x_algor.o: ../../include/openssl/asn1.h ../../include/openssl/asn1_mac.h x_algor.o: ../../include/openssl/bio.h ../../include/openssl/blowfish.h x_algor.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c index 3a0c0c783..b57aa27ef 100644 --- a/crypto/asn1/a_bytes.c +++ b/crypto/asn1/a_bytes.c @@ -71,6 +71,12 @@ B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,0, B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, }; +unsigned long ASN1_tag2bit(int tag) +{ + if((tag < 0) || (tag > 30)) return 0; + return tag2bit[tag]; +} + static int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c); /* type is a 'bitmap' of acceptable string types. */ diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 3daf4e483..41da44772 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -84,6 +84,7 @@ extern "C" { #define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ #define V_ASN1_OTHER -3 /* used in ASN1_TYPE */ +#define V_ASN1_ANY -3 /* used in ASN1 template code */ #define V_ASN1_NEG 0x100 /* negative flag */ @@ -237,6 +238,7 @@ DECLARE_STACK_OF(ASN1_STRING_TABLE) #define ASN1_VISIBLESTRING ASN1_STRING #define ASN1_UTF8STRING ASN1_STRING #define ASN1_BOOLEAN int +#define ASN1_NULL int #else typedef struct asn1_string_st ASN1_INTEGER; typedef struct asn1_string_st ASN1_ENUMERATED; @@ -254,9 +256,17 @@ typedef struct asn1_string_st ASN1_GENERALIZEDTIME; typedef struct asn1_string_st ASN1_VISIBLESTRING; typedef struct asn1_string_st ASN1_UTF8STRING; typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; #endif -typedef int ASN1_NULL; +/* Declarations for template structures: for full definitions + * see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; /* Parameters used by ASN1_STRING_print_ex() */ @@ -787,6 +797,7 @@ int ASN1_PRINTABLE_type(unsigned char *s, int max); int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass); ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, unsigned char **pp, long length, int Ptag, int Pclass); +unsigned long ASN1_tag2bit(int tag); /* type is one or more of the B_ASN1_ values. */ ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,unsigned char **pp, long length,int type); @@ -873,6 +884,37 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); void ASN1_STRING_TABLE_cleanup(void); +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE * ASN1_item_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); + +int ASN1_item_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +int ASN1_template_new(ASN1_VALUE **val, const ASN1_TEMPLATE *tt); +int ASN1_primitive_new(ASN1_VALUE **val, long utype); + +void ASN1_template_free(ASN1_VALUE *arg, const ASN1_TEMPLATE *tt); +int ASN1_template_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt); +int ASN1_item_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +int ASN1_template_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_TEMPLATE *tt); +void ASN1_primitive_free(ASN1_VALUE *val, long utype); + +int asn1_get_choice_selector(ASN1_VALUE *data, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **data, int value, const ASN1_ITEM *it); +ASN1_VALUE * asn1_get_field(ASN1_VALUE *data, const ASN1_TEMPLATE *tt); +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **data, const ASN1_TEMPLATE *tt); +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE *val, const ASN1_TEMPLATE *tt); +int asn1_template_is_bool(const ASN1_TEMPLATE *tt); +int asn1_item_is_bool(const ASN1_ITEM *it); + + + /* 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. @@ -886,8 +928,11 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_A2I_ASN1_INTEGER 101 #define ASN1_F_A2I_ASN1_STRING 102 #define ASN1_F_ACCESS_DESCRIPTION_NEW 291 +#define ASN1_F_ASN1_CHECK_TLEN 293 #define ASN1_F_ASN1_COLLATE_PRIMITIVE 103 +#define ASN1_F_ASN1_COLLECT 294 #define ASN1_F_ASN1_D2I_BIO 104 +#define ASN1_F_ASN1_D2I_EX_PRIMITIVE 295 #define ASN1_F_ASN1_D2I_FP 105 #define ASN1_F_ASN1_DUP 106 #define ASN1_F_ASN1_ENUMERATED_SET 232 @@ -899,6 +944,8 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_ASN1_I2D_FP 110 #define ASN1_F_ASN1_INTEGER_SET 111 #define ASN1_F_ASN1_INTEGER_TO_BN 112 +#define ASN1_F_ASN1_ITEM_EX_D2I 296 +#define ASN1_F_ASN1_ITEM_NEW 297 #define ASN1_F_ASN1_MBSTRING_COPY 282 #define ASN1_F_ASN1_OBJECT_NEW 113 #define ASN1_F_ASN1_PACK_STRING 245 @@ -909,6 +956,9 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_ASN1_STRING_NEW 115 #define ASN1_F_ASN1_STRING_TABLE_ADD 283 #define ASN1_F_ASN1_STRING_TYPE_NEW 116 +#define ASN1_F_ASN1_TEMPLATE_D2I 298 +#define ASN1_F_ASN1_TEMPLATE_EX_D2I 299 +#define ASN1_F_ASN1_TEMPLATE_NEW 300 #define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 117 #define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 118 #define ASN1_F_ASN1_TYPE_NEW 119 @@ -919,6 +969,7 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_BASIC_CONSTRAINTS_NEW 226 #define ASN1_F_BN_TO_ASN1_ENUMERATED 234 #define ASN1_F_BN_TO_ASN1_INTEGER 122 +#define ASN1_F_COLLECT_DATA 301 #define ASN1_F_D2I_ACCESS_DESCRIPTION 284 #define ASN1_F_D2I_ASN1_BIT_STRING 123 #define ASN1_F_D2I_ASN1_BMPSTRING 124 @@ -956,21 +1007,6 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_D2I_NETSCAPE_SPKAC 143 #define ASN1_F_D2I_NETSCAPE_SPKI 144 #define ASN1_F_D2I_NOTICEREF 268 -#define ASN1_F_D2I_OCSP_BASICRESP 293 -#define ASN1_F_D2I_OCSP_CERTID 294 -#define ASN1_F_D2I_OCSP_CERTSTATUS 295 -#define ASN1_F_D2I_OCSP_CRLID 296 -#define ASN1_F_D2I_OCSP_ONEREQ 297 -#define ASN1_F_D2I_OCSP_REQINFO 298 -#define ASN1_F_D2I_OCSP_REQUEST 299 -#define ASN1_F_D2I_OCSP_RESPBYTES 300 -#define ASN1_F_D2I_OCSP_RESPDATA 301 -#define ASN1_F_D2I_OCSP_RESPID 302 -#define ASN1_F_D2I_OCSP_RESPONSE 303 -#define ASN1_F_D2I_OCSP_REVOKEDINFO 304 -#define ASN1_F_D2I_OCSP_SERVICELOC 305 -#define ASN1_F_D2I_OCSP_SIGNATURE 306 -#define ASN1_F_D2I_OCSP_SINGLERESP 307 #define ASN1_F_D2I_OTHERNAME 287 #define ASN1_F_D2I_PBE2PARAM 262 #define ASN1_F_D2I_PBEPARAM 249 @@ -1042,21 +1078,6 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_F_NETSCAPE_SPKAC_NEW 190 #define ASN1_F_NETSCAPE_SPKI_NEW 191 #define ASN1_F_NOTICEREF_NEW 272 -#define ASN1_F_OCSP_BASICRESP_NEW 308 -#define ASN1_F_OCSP_CERTID_NEW 309 -#define ASN1_F_OCSP_CERTSTATUS_NEW 310 -#define ASN1_F_OCSP_CRLID_NEW 311 -#define ASN1_F_OCSP_ONEREQ_NEW 312 -#define ASN1_F_OCSP_REQINFO_NEW 313 -#define ASN1_F_OCSP_REQUEST_NEW 314 -#define ASN1_F_OCSP_RESPBYTES_NEW 315 -#define ASN1_F_OCSP_RESPDATA_NEW 316 -#define ASN1_F_OCSP_RESPID_NEW 317 -#define ASN1_F_OCSP_RESPONSE_NEW 318 -#define ASN1_F_OCSP_REVOKEDINFO_NEW 319 -#define ASN1_F_OCSP_SERVICELOC_NEW 320 -#define ASN1_F_OCSP_SIGNATURE_NEW 321 -#define ASN1_F_OCSP_SINGLERESP_NEW 322 #define ASN1_F_OTHERNAME_NEW 288 #define ASN1_F_PBE2PARAM_NEW 264 #define ASN1_F_PBEPARAM_NEW 251 @@ -1133,10 +1154,14 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_R_EXPECTING_A_NULL 164 #define ASN1_R_EXPECTING_A_TIME 152 #define ASN1_R_EXPECTING_A_UTCTIME 118 +#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 167 +#define ASN1_R_FIELD_MISSING 168 #define ASN1_R_FIRST_NUM_TOO_LARGE 119 #define ASN1_R_GENERALIZEDTIME_TOO_LONG 153 #define ASN1_R_HEADER_TOO_LONG 120 #define ASN1_R_ILLEGAL_CHARACTERS 158 +#define ASN1_R_ILLEGAL_NULL 169 +#define ASN1_R_ILLEGAL_TAGGED_ANY 170 #define ASN1_R_INVALID_BMPSTRING_LENGTH 159 #define ASN1_R_INVALID_DIGIT 121 #define ASN1_R_INVALID_SEPARATOR 122 @@ -1145,22 +1170,30 @@ void ASN1_STRING_TABLE_cleanup(void); #define ASN1_R_INVALID_UTF8STRING 161 #define ASN1_R_IV_TOO_LARGE 124 #define ASN1_R_LENGTH_ERROR 125 +#define ASN1_R_MISSING_EOC 171 #define ASN1_R_MISSING_SECOND_NUMBER 126 +#define ASN1_R_MSTRING_NOT_UNIVERSAL 172 +#define ASN1_R_MSTRING_WRONG_TAG 173 #define ASN1_R_NON_HEX_CHARACTERS 127 #define ASN1_R_NOT_ENOUGH_DATA 128 +#define ASN1_R_NO_MATCHING_CHOICE_TYPE 174 #define ASN1_R_NULL_IS_WRONG_LENGTH 165 #define ASN1_R_ODD_NUMBER_OF_CHARS 129 #define ASN1_R_PARSING 130 #define ASN1_R_PRIVATE_KEY_HEADER_MISSING 131 #define ASN1_R_SECOND_NUMBER_TOO_LARGE 132 +#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 175 +#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 176 #define ASN1_R_SHORT_LINE 133 #define ASN1_R_STRING_TOO_LONG 163 #define ASN1_R_STRING_TOO_SHORT 134 #define ASN1_R_TAG_VALUE_TOO_HIGH 135 #define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 136 #define ASN1_R_TOO_LONG 137 +#define ASN1_R_TYPE_NOT_CONSTRUCTED 177 #define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 138 #define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 139 +#define ASN1_R_UNEXPECTED_EOC 178 #define ASN1_R_UNKNOWN_ATTRIBUTE_TYPE 140 #define ASN1_R_UNKNOWN_FORMAT 162 #define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 141 diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index 3a53cb33c..7d84bf61a 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -71,8 +71,11 @@ static ERR_STRING_DATA ASN1_str_functs[]= {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_ACCESS_DESCRIPTION_NEW,0), "ACCESS_DESCRIPTION_new"}, +{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"}, {ERR_PACK(0,ASN1_F_ASN1_D2I_BIO,0), "ASN1_d2i_bio"}, +{ERR_PACK(0,ASN1_F_ASN1_D2I_EX_PRIMITIVE,0), "ASN1_D2I_EX_PRIMITIVE"}, {ERR_PACK(0,ASN1_F_ASN1_D2I_FP,0), "ASN1_d2i_fp"}, {ERR_PACK(0,ASN1_F_ASN1_DUP,0), "ASN1_dup"}, {ERR_PACK(0,ASN1_F_ASN1_ENUMERATED_SET,0), "ASN1_ENUMERATED_set"}, @@ -84,6 +87,8 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_I2D_FP,0), "ASN1_i2d_fp"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_SET,0), "ASN1_INTEGER_set"}, {ERR_PACK(0,ASN1_F_ASN1_INTEGER_TO_BN,0), "ASN1_INTEGER_to_BN"}, +{ERR_PACK(0,ASN1_F_ASN1_ITEM_EX_D2I,0), "ASN1_item_ex_d2i"}, +{ERR_PACK(0,ASN1_F_ASN1_ITEM_NEW,0), "ASN1_item_new"}, {ERR_PACK(0,ASN1_F_ASN1_MBSTRING_COPY,0), "ASN1_mbstring_copy"}, {ERR_PACK(0,ASN1_F_ASN1_OBJECT_NEW,0), "ASN1_OBJECT_new"}, {ERR_PACK(0,ASN1_F_ASN1_PACK_STRING,0), "ASN1_pack_string"}, @@ -94,6 +99,9 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_ASN1_STRING_NEW,0), "ASN1_STRING_new"}, {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"}, +{ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_EX_D2I,0), "ASN1_TEMPLATE_EX_D2I"}, +{ERR_PACK(0,ASN1_F_ASN1_TEMPLATE_NEW,0), "ASN1_template_new"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING,0), "ASN1_TYPE_get_int_octetstring"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_OCTETSTRING,0), "ASN1_TYPE_get_octetstring"}, {ERR_PACK(0,ASN1_F_ASN1_TYPE_NEW,0), "ASN1_TYPE_new"}, @@ -104,6 +112,7 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_BASIC_CONSTRAINTS_NEW,0), "BASIC_CONSTRAINTS_new"}, {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"}, {ERR_PACK(0,ASN1_F_D2I_ACCESS_DESCRIPTION,0), "d2i_ACCESS_DESCRIPTION"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_BIT_STRING,0), "d2i_ASN1_BIT_STRING"}, {ERR_PACK(0,ASN1_F_D2I_ASN1_BMPSTRING,0), "d2i_ASN1_BMPSTRING"}, @@ -141,21 +150,6 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_D2I_NETSCAPE_SPKAC,0), "d2i_NETSCAPE_SPKAC"}, {ERR_PACK(0,ASN1_F_D2I_NETSCAPE_SPKI,0), "d2i_NETSCAPE_SPKI"}, {ERR_PACK(0,ASN1_F_D2I_NOTICEREF,0), "d2i_NOTICEREF"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_BASICRESP,0), "d2i_OCSP_BASICRESP"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_CERTID,0), "d2i_OCSP_CERTID"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_CERTSTATUS,0), "d2i_OCSP_CERTSTATUS"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_CRLID,0), "d2i_OCSP_CRLID"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_ONEREQ,0), "d2i_OCSP_ONEREQ"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_REQINFO,0), "d2i_OCSP_REQINFO"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_REQUEST,0), "d2i_OCSP_REQUEST"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_RESPBYTES,0), "d2i_OCSP_RESPBYTES"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_RESPDATA,0), "d2i_OCSP_RESPDATA"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_RESPID,0), "d2i_OCSP_RESPID"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_RESPONSE,0), "d2i_OCSP_RESPONSE"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_REVOKEDINFO,0), "d2i_OCSP_REVOKEDINFO"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_SERVICELOC,0), "d2i_OCSP_SERVICELOC"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_SIGNATURE,0), "d2i_OCSP_SIGNATURE"}, -{ERR_PACK(0,ASN1_F_D2I_OCSP_SINGLERESP,0), "d2i_OCSP_SINGLERESP"}, {ERR_PACK(0,ASN1_F_D2I_OTHERNAME,0), "d2i_OTHERNAME"}, {ERR_PACK(0,ASN1_F_D2I_PBE2PARAM,0), "d2i_PBE2PARAM"}, {ERR_PACK(0,ASN1_F_D2I_PBEPARAM,0), "d2i_PBEPARAM"}, @@ -227,21 +221,6 @@ static ERR_STRING_DATA ASN1_str_functs[]= {ERR_PACK(0,ASN1_F_NETSCAPE_SPKAC_NEW,0), "NETSCAPE_SPKAC_new"}, {ERR_PACK(0,ASN1_F_NETSCAPE_SPKI_NEW,0), "NETSCAPE_SPKI_new"}, {ERR_PACK(0,ASN1_F_NOTICEREF_NEW,0), "NOTICEREF_new"}, -{ERR_PACK(0,ASN1_F_OCSP_BASICRESP_NEW,0), "OCSP_BASICRESP_new"}, -{ERR_PACK(0,ASN1_F_OCSP_CERTID_NEW,0), "OCSP_CERTID_new"}, -{ERR_PACK(0,ASN1_F_OCSP_CERTSTATUS_NEW,0), "OCSP_CERTSTATUS_new"}, -{ERR_PACK(0,ASN1_F_OCSP_CRLID_NEW,0), "OCSP_CRLID_new"}, -{ERR_PACK(0,ASN1_F_OCSP_ONEREQ_NEW,0), "OCSP_ONEREQ_new"}, -{ERR_PACK(0,ASN1_F_OCSP_REQINFO_NEW,0), "OCSP_REQINFO_new"}, -{ERR_PACK(0,ASN1_F_OCSP_REQUEST_NEW,0), "OCSP_REQUEST_new"}, -{ERR_PACK(0,ASN1_F_OCSP_RESPBYTES_NEW,0), "OCSP_RESPBYTES_new"}, -{ERR_PACK(0,ASN1_F_OCSP_RESPDATA_NEW,0), "OCSP_RESPDATA_new"}, -{ERR_PACK(0,ASN1_F_OCSP_RESPID_NEW,0), "OCSP_RESPID_new"}, -{ERR_PACK(0,ASN1_F_OCSP_RESPONSE_NEW,0), "OCSP_RESPONSE_new"}, -{ERR_PACK(0,ASN1_F_OCSP_REVOKEDINFO_NEW,0), "OCSP_REVOKEDINFO_new"}, -{ERR_PACK(0,ASN1_F_OCSP_SERVICELOC_NEW,0), "OCSP_SERVICELOC_new"}, -{ERR_PACK(0,ASN1_F_OCSP_SIGNATURE_NEW,0), "OCSP_SIGNATURE_new"}, -{ERR_PACK(0,ASN1_F_OCSP_SINGLERESP_NEW,0), "OCSP_SINGLERESP_new"}, {ERR_PACK(0,ASN1_F_OTHERNAME_NEW,0), "OTHERNAME_new"}, {ERR_PACK(0,ASN1_F_PBE2PARAM_NEW,0), "PBE2PARAM_new"}, {ERR_PACK(0,ASN1_F_PBEPARAM_NEW,0), "PBEPARAM_new"}, @@ -321,10 +300,14 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_EXPECTING_A_NULL ,"expecting a null"}, {ASN1_R_EXPECTING_A_TIME ,"expecting a time"}, {ASN1_R_EXPECTING_A_UTCTIME ,"expecting a utctime"}, +{ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED ,"explicit tag not constructed"}, +{ASN1_R_FIELD_MISSING ,"field missing"}, {ASN1_R_FIRST_NUM_TOO_LARGE ,"first num too large"}, {ASN1_R_GENERALIZEDTIME_TOO_LONG ,"generalizedtime too long"}, {ASN1_R_HEADER_TOO_LONG ,"header too long"}, {ASN1_R_ILLEGAL_CHARACTERS ,"illegal characters"}, +{ASN1_R_ILLEGAL_NULL ,"illegal null"}, +{ASN1_R_ILLEGAL_TAGGED_ANY ,"illegal tagged any"}, {ASN1_R_INVALID_BMPSTRING_LENGTH ,"invalid bmpstring length"}, {ASN1_R_INVALID_DIGIT ,"invalid digit"}, {ASN1_R_INVALID_SEPARATOR ,"invalid separator"}, @@ -333,22 +316,30 @@ static ERR_STRING_DATA ASN1_str_reasons[]= {ASN1_R_INVALID_UTF8STRING ,"invalid utf8string"}, {ASN1_R_IV_TOO_LARGE ,"iv too large"}, {ASN1_R_LENGTH_ERROR ,"length error"}, +{ASN1_R_MISSING_EOC ,"missing eoc"}, {ASN1_R_MISSING_SECOND_NUMBER ,"missing second number"}, +{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_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_ODD_NUMBER_OF_CHARS ,"odd number of chars"}, {ASN1_R_PARSING ,"parsing"}, {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_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_TOO_LONG ,"too long"}, +{ASN1_R_TYPE_NOT_CONSTRUCTED ,"type not constructed"}, {ASN1_R_UNABLE_TO_DECODE_RSA_KEY ,"unable to decode rsa key"}, {ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY ,"unable to decode rsa private key"}, +{ASN1_R_UNEXPECTED_EOC ,"unexpected eoc"}, {ASN1_R_UNKNOWN_ATTRIBUTE_TYPE ,"unknown attribute type"}, {ASN1_R_UNKNOWN_FORMAT ,"unknown format"}, {ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM ,"unknown message digest algorithm"}, diff --git a/crypto/asn1/asn1t.h b/crypto/asn1/asn1t.h new file mode 100644 index 000000000..186afeab6 --- /dev/null +++ b/crypto/asn1/asn1t.h @@ -0,0 +1,512 @@ +/* asnt.h */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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). + * + */ +#ifndef HEADER_ASNT_H +#define HEADER_ASNT_H + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros to aid ASN1 template writing */ + +/* This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * ASN1_SEQUENCE_END(stname); + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * ASN1_SEQUENCE_END_name(stname, itname); + * + * This will create an item called itname_it using + * a structure called stname. + */ + +#define ASN1_SEQUENCE(tname) \ + const static ASN1_TEMPLATE tname##_seq_tt[] + +#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +#define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + const ASN1_ITEM tname##_it = { \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + } + + +/* This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname); + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type' + */ + +#define ASN1_CHOICE(tname) \ + const static ASN1_TEMPLATE tname##_ch_tt[] + +#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +#define ASN1_CHOICE_END_name(stname, tname) \ + ;\ + ASN1_ITEM tname##_it = { \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,type) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + } + + + + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, &(type##_it) } + +#define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +#define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Plain simple type */ +#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +#define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +#define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +#define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +#define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* This is the ASN1 template structure that defines + * a wrapper round the actual type. It determines the + * actual position of the field in the value structure, + * various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { +unsigned long flags; /* Various flags */ +long tag; /* tag, not used if no tagging */ +unsigned long offset; /* Offset of this field in structure */ +#ifndef NO_ASN1_FIELD_NAMES +char *field_name; /* Field name */ +#endif +const void *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE *tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +#define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +#define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +#define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* These flags mean the tag should be taken from the + * tag field. If EXPLICIT then the underlying type + * is used for the inner tag. + */ + +/* IMPLICIT tagging */ +#define ASN1_TFLG_IMPTAG (0x1 << 3) + + +/* EXPLICIT tagging, inner tag from underlying type */ +#define ASN1_TFLG_EXPTAG (0x2 << 3) + +#define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* If tagging is in force these determine the + * type of tag to use. Otherwise the tag is + * determined by the underlying type. These + * values reflect the actual octet format. + */ + +/* Universal tag */ +#define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +#define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +#define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +#define ASN1_TFLG_PRIVATE (0x3<<6) + +#define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* These are for ANY DEFINED BY type. In this case + * the 'item' field points to an ASN1_ADB structure + * which contains a table of values to decode the + * relevant type + */ + +#define ASN1_TFLG_ADB_MASK (0x3<<8) + +#define ASN1_TFLG_ADB_OID (0x1<<8) + +#define ASN1_TFLG_ADB_INT (0x1<<9) + + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { +char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ +long utype; /* underlying type */ +const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ +long tcount; /* Number of templates if SEQUENCE or CHOICE */ +const void *funcs; /* functions that handle this type */ +long size; /* Structure size (usually)*/ +#ifndef NO_ASN1_FIELD_NAMES +const char *sname; /* Structure name */ +#endif +}; + +/* These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * For COMPAT types the funcs field gives a + * set of functions that handle this type, this + * supports the old d2i, i2d convention. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + */ + +#define ASN1_ITYPE_PRIMITIVE 0x0 + +#define ASN1_ITYPE_SEQUENCE 0x1 + +#define ASN1_ITYPE_CHOICE 0x2 + +#define ASN1_ITYPE_COMPAT 0x3 + +#define ASN1_ITYPE_EXTERN 0x4 + +#define ASN1_ITYPE_MSTRING 0x5 + +/* Cache for ASN1 tag and length, so we + * don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st{ + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 functions */ + +typedef ASN1_VALUE * ASN1_new_func(void); +typedef void ASN1_free_func(ASN1_VALUE *a); +typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, unsigned char ** in, long length); +typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in); + +typedef int ASN1_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **val, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE *val, const ASN1_ITEM *it); + +typedef struct ASN1_COMPAT_FUNCS_st { + ASN1_new_func *asn1_new; + ASN1_free_func *asn1_free; + ASN1_d2i_func *asn1_d2i; + ASN1_i2d_func *asn1_i2d; +} ASN1_COMPAT_FUNCS; + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; +} ASN1_EXTERN_FUNCS; + +/* Macro to implement an ASN1_ITEM in terms of old style funcs */ + +#define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE) + +#define IMPLEMENT_COMPAT_ASN1_type(sname, type) \ + static const ASN1_COMPAT_FUNCS sname##_ff = { \ + (ASN1_new_func *)sname##_new, \ + (ASN1_free_func *)sname##_free, \ + (ASN1_d2i_func *)d2i_##sname, \ + (ASN1_i2d_func *)i2d_##sname, \ + }; \ + ASN1_ITEM const sname##_it = { \ + ASN1_ITYPE_COMPAT, \ + type, \ + NULL, \ + 0, \ + &sname##_ff, \ + 0, \ + #sname \ + } + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +#define IMPLEMENT_ASN1(type) \ + (type *) type##_new(void) \ + { \ + return ASN1_item_new(&type##_it); \ + } \ + void type##_free(type *a) \ + { \ + return ASN1_item_free(a, &type##_it); \ + } + +/* external definitions for primitive types */ + +extern const ASN1_ITEM ASN1_BOOLEAN_it; +extern const ASN1_ITEM ASN1_INTEGER_it; +extern const ASN1_ITEM ASN1_BIT_STRING_it; +extern const ASN1_ITEM ASN1_OCTET_STRING_it; +extern const ASN1_ITEM ASN1_NULL_it; +extern const ASN1_ITEM ASN1_OBJECT_it; +extern const ASN1_ITEM ASN1_ENUMERATED_it; +extern const ASN1_ITEM ASN1_UTF8STRING_it; +extern const ASN1_ITEM ASN1_PRINTABLESTRING_it; +extern const ASN1_ITEM ASN1_T61STRING_it; +extern const ASN1_ITEM ASN1_IA5STRING_it; +extern const ASN1_ITEM ASN1_UTCTIME_it; +extern const ASN1_ITEM ASN1_GENERALIZEDTIME_it; +extern const ASN1_ITEM ASN1_VISIBLESTRING_it; +extern const ASN1_ITEM ASN1_UNIVERSALSTRING_it; +extern const ASN1_ITEM ASN1_BMPSTRING_it; +extern const ASN1_ITEM ASN1_ANY_it; + +#if 0 + +int ASN1_item_new(void *arg, const ASN1_ITEM *it); +int ASN1_template_new(void *arg, const ASN1_TEMPLATE *tt); +void *ASN1_primitive_new(long utype); + +void ASN1_item_free(void *field, const ASN1_ITEM *it); +void ASN1_template_free(void *arg, const ASN1_TEMPLATE *tt); + +int ASN1_item_d2i(void *dptr, unsigned char **in, long len, const ASN1_ITEM *it); +int ASN1_template_d2i(void *dptr, unsigned char **in, long len, const ASN1_TEMPLATE *tt); +int ASN1_item_ex_d2i(void *dptr, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +int ASN1_item_i2d(void *data, unsigned char **out, const ASN1_ITEM *it); +int ASN1_item_ex_i2d(void *data, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +int ASN1_template_i2d(void *data, unsigned char **out, const ASN1_TEMPLATE *tt); +void ASN1_primitive_free(void *type, long utype); + +int asn1_get_choice_selector(void *data, const ASN1_ITEM *it); +int asn1_set_choice_selector(void **data, int value, const ASN1_ITEM *it); +void *asn1_get_field(void *data, const ASN1_TEMPLATE *tt); +void *asn1_get_field_ptr(void **data, const ASN1_TEMPLATE *tt); +const ASN1_TEMPLATE *asn1_do_adb(void *data, const ASN1_TEMPLATE *tt); +int asn1_template_is_bool(const ASN1_TEMPLATE *tt); +int asn1_item_is_bool(const ASN1_ITEM *it); + +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c new file mode 100644 index 000000000..260fc7b54 --- /dev/null +++ b/crypto/asn1/tasn_dec.c @@ -0,0 +1,810 @@ +/* tasn_dec.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/err.h> + +static int asn1_check_eoc(unsigned char **in, long len); +static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag); +static int collect_data(BUF_MEM *buf, unsigned char **p, long plen); +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, + unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx); +static int asn1_template_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long len, + int utype, int tag, int aclass, char opt, ASN1_TLC *ctx); + +/* Macro to initialize and invalidate the cache */ + +#define asn1_tlc_clear(c) if(c) (c)->valid = 0 + +/* Decode an ASN1 item, this currently behaves just + * like a standard 'd2i' function. 'in' points to + * a buffer to read the data from, in future we will + * have more advanced versions that can input data + * a piece at a time and this will simply be a special + * case. + */ + +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it) +{ + ASN1_TLC c; + ASN1_VALUE *ptmpval = NULL; + if(!pval) pval = &ptmpval; + asn1_tlc_clear(&c); + if(ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) + return *pval; + return NULL; +} + +int ASN1_template_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_TEMPLATE *tt) +{ + ASN1_TLC c; + asn1_tlc_clear(&c); + return asn1_template_ex_d2i(pval, in, len, tt, 0, &c); +} + + +/* Decode an item, taking care of IMPLICIT tagging, if any. + * If 'opt' set and tag mismatch return -1 to handle OPTIONAL + */ + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + const ASN1_TEMPLATE *tt; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + unsigned char *p, *q, imphack = 0, oclass; + char seq_eoc, cst, isopt; + int i; + int otag; + int ret = 0; + ASN1_VALUE *pchval, **pchptr, *ptmpval; + if(!pval) return 0; + + tt = NULL; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx); + return asn1_d2i_ex_primitive(pval, in, len, it->utype, tag, aclass, opt, ctx); + break; + + case ASN1_ITYPE_MSTRING: + p = *in; + /* Just read in tag and class */ + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, &p, len, -1, 0, 1, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + /* Must be UNIVERSAL class */ + if(oclass != V_ASN1_UNIVERSAL) { + /* If OPTIONAL, assume this is OK */ + if(opt) return -1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); + goto err; + } + /* Check tag matches bit map */ + if(ASN1_tag2bit(otag) & it->utype) { + /* If OPTIONAL, assume this is OK */ + if(opt) return -1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MSTRING_WRONG_TAG); + goto err; + } + return asn1_d2i_ex_primitive(pval, in, len, otag, -1, 0, 1, ctx); + + case ASN1_ITYPE_EXTERN: + /* Use new style d2i */ + ef = it->funcs; + return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); + + case ASN1_ITYPE_COMPAT: + /* we must resort to old style evil hackery */ + cf = it->funcs; + + /* If OPTIONAL see if it is there */ + if(opt) { + int exptag; + p = *in; + if(tag == -1) exptag = it->utype; + else exptag = tag; + /* Don't care about anything other than presence of expected tag */ + ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL, &p, len, exptag, aclass, 1, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + if(ret == -1) return -1; + } + /* This is the old style evil hack IMPLICIT handling: + * since the underlying code is expecting a tag and + * class other than the one present we change the + * buffer temporarily then change it back afterwards. + * This doesn't and never did work for tags > 30. + * + * Yes this is *horrible* but it is only needed for + * old style d2i which will hopefully not be around + * for much longer. + * FIXME: should copy the buffer then modify it so + * the input buffer can be const: we should *always* + * copy because the old style d2i might modify the + * buffer. + */ + + if(tag != -1) { + p = *in; + imphack = *p; + *p = (*p & V_ASN1_CONSTRUCTED) | it->utype; + } + + ptmpval = cf->asn1_d2i(pval, in, len); + + if(tag != -1) *p = imphack; + + if(ptmpval) return 1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + + + case ASN1_ITYPE_CHOICE: + /* CHOICE type, try each possibility in turn */ + pchval = NULL; + p = *in; + for(i = 0, tt=it->templates; i < it->tcount; i++, tt++) { + /* We mark field as OPTIONAL so its absence + * can be recognised. + */ + ret = asn1_template_ex_d2i(&pchval, &p, len, tt, 1, ctx); + /* If field not present, try the next one */ + if(ret == -1) continue; + /* If positive return, read OK, break loop */ + if(ret > 0) break; + /* Otherwise must be an ASN1 parsing error */ + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + /* FIXME: note choice type that did this */ + return 0; + } + /* Did we fall off the end without reading anything? */ + if(i == it->tcount) { + /* If OPTIONAL, this is OK */ + if(opt) return -1; + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); + return 0; + } + /* Otherwise we got a match, allocate structure and populate it */ + if(!*pval) { + if(!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + } + pchptr = asn1_get_field_ptr(pval, tt); + *pchptr = pchval; + asn1_set_choice_selector(pval, i, it); + *in = p; + return 1; + + case ASN1_ITYPE_SEQUENCE: + p = *in; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if(tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* Get SEQUENCE length and update len, p */ + ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, &p, len, tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + if(!cst) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); + goto err; + } + + if(!*pval) { + if(!ASN1_item_ex_new(pval, it)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + } + + /* Get each field entry */ + for(i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE **pseqval; + seqtt = asn1_do_adb(*pval, tt); + pseqval = asn1_get_field_ptr(pval, seqtt); + /* Have we ran out of data? */ + if(!len) break; + q = p; + if(asn1_check_eoc(&p, len)) { + if(!seq_eoc) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + seq_eoc = 0; + q = p; + break; + } + /* This determines the OPTIONAL flag value. The field cannot + * be omitted if it is the last of a SEQUENCE and there is + * still data to be read. This isn't strictly necessary but + * it increases efficiency in some cases. + */ + isopt = (i == (it->tcount - 1)) ? 0 : seqtt->flags & ASN1_TFLG_OPTIONAL; + /* attempt to read in field, allowing each to be OPTIONAL */ + ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx); + if(!ret) { + /* Add error field info */ + goto err; + } else if(ret == -1) { + /* OPTIONAL component absent. + * Since this is the only place we take any notice of + * OPTIONAL this is the only place we need to handle freeing + * and zeroing the field. + * BOOLEAN is a special case as always and must be set to -1. + */ + if(asn1_template_is_bool(seqtt)) + *(int *)pseqval = -1; + else if(*pseqval) { + ASN1_template_free(*pseqval, seqtt); + *pseqval = NULL; + } + continue; + } + /* Update length */ + len -= p - q; + } + /* Check for EOC if expecting one */ + if(seq_eoc) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_MISSING_EOC); + goto err; + } + /* Check all data read */ + if(len) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); + goto err; + } + + /* If we get here we've got no more data in the SEQUENCE, + * however we may not have read all fields so check all + * remaining are OPTIONAL. + */ + for(; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + seqtt = asn1_do_adb(*pval, tt); + if(!(tt->flags & ASN1_TFLG_OPTIONAL)) { + ASN1err(ASN1_F_ASN1_ITEM_EX_D2I, ASN1_R_FIELD_MISSING); + goto err; + } + } + + *in = p; + return 1; + + default: + return 0; + } + err: + ASN1_item_free(*pval, it); + *pval = NULL; + if(tt) ERR_add_error_data(4, "Field=", tt->field_name, ", Structure=", it->sname); + else ERR_add_error_data(2, "Structure=", it->sname); + return 0; +} + +int asn1_template_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx) +{ + int flags, aclass; + int ret; + unsigned char *p, *q; + char exp_eoc; + if(!val) return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + + p = *in; + q = p; + + /* If explicit tag expected then swallow it */ + if(flags & ASN1_TFLG_EXPTAG) { + char cst; + /* This updates 'len' to the amount of data inside the EXPLICIT tag: + * this is what is available to the rest of the structure. If INDEF then this + * just subtracts the header length, leaving us enough room for the + * data and the expected EOC. + */ + /* FIXME: this doesn't get things right if it and the enclosed stuff is NDEF. + * also we need to avoid trailing garbage before the end of the tag + */ + ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, &p, len, tt->tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + if(!cst) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); + return 0; + } + /* We've found the field so it can't be OPTIONAL now */ + opt = 0; + } else exp_eoc = 0; + + if(flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + int sktag, skaclass; + char sk_eoc; + /* First work out expected inner tag value */ + if(flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if(flags & ASN1_TFLG_SET_OF) sktag = V_ASN1_SET; + else sktag = V_ASN1_SEQUENCE; + } + /* Get the tag */ + ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, &p, len, sktag, skaclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + if(!(*val = (ASN1_VALUE *)sk_new_null())) { + ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_MALLOC_FAILURE); + goto err; + } + /* Read as many items as we can */ + while(len > 0) { + ASN1_VALUE *skfield; + /* See if EOC found */ + q = p; + if(asn1_check_eoc(&p, len)) { + if(!sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_UNEXPECTED_EOC); + goto err; + } + len -= p - q; + sk_eoc = 0; + break; + } + skfield = NULL; + if(!ASN1_item_ex_d2i(&skfield, &p, len, tt->item, -1, 0, 0, ctx)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } + len -= p - q; + if(!sk_push((STACK *)*val, (char *)skfield)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if(sk_eoc) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_MISSING_EOC); + goto err; + } + } else if(flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + ret = ASN1_item_ex_d2i(val, &p, len, tt->item, tt->tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + } else { + /* Nothing special */ + ret = ASN1_item_ex_d2i(val, &p, len, tt->item, -1, 0, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ERR_R_NESTED_ASN1_ERROR); + goto err; + } else if(ret == -1) return -1; + } + + if(exp_eoc && !asn1_check_eoc(&p, len)) { + ASN1err(ASN1_F_ASN1_TEMPLATE_D2I, ASN1_R_MISSING_EOC); + goto err; + } + + *in = p; + return 1; + + err: + ASN1_template_free(*val, tt); + *val = NULL; + return 0; +} + +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inlen, int utype, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + int ret = 0; + long plen; + char cst, inf; + unsigned char *p; + BUF_MEM buf; + unsigned char *cont = NULL; + ASN1_STRING *stmp; + int *tbool; + long len; + if(!*pval) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); + return 0; /* Should never happen */ + } + if(utype == V_ASN1_ANY) { + int otag; + unsigned char oclass; + ASN1_TYPE *ttmp; + ASN1_VALUE *anytype; + if(tag >= 0) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); + return 0; + } + p = *in; + ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, &p, inlen, -1, 0, 0, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + if(oclass != V_ASN1_UNIVERSAL) otag = V_ASN1_UNDEF; + anytype = NULL; + ret = asn1_d2i_ex_primitive(&anytype, in, inlen, otag, -1, 0, 0, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + if(*pval) ASN1_TYPE_free((ASN1_TYPE *)*pval); + ttmp = ASN1_TYPE_new(); + *pval = (ASN1_VALUE *)ttmp; + if(!ttmp) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + return 0; + } + if(otag != V_ASN1_NULL) ttmp->value.ptr = (char *)anytype; + ttmp->type = otag; + return 1; + + } + if(tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + p = *in; + /* Check header */ + ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, &p, inlen, tag, aclass, opt, ctx); + if(!ret) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); + return 0; + } else if(ret == -1) return -1; + /* SEQUENCE and SET must be constructed */ + if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET)) { + if(!cst) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_CONSTRUCTED); + return 0; + } + /* FIXME: if it is indefinite length constructed need to work out + * actual length. + */ + len = inlen; + } else if(cst) { + buf.length = 0; + buf.max = 0; + buf.data = NULL; + asn1_collect(&buf, &p, plen, inf, -1); + cont = (unsigned char *)buf.data; + len = buf.length; + } else { + cont = p; + len = plen; + p += plen; + } + + switch(utype) { + case V_ASN1_OBJECT: + if(!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) goto err; + break; + + case V_ASN1_NULL: + if(plen) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_NULL_IS_WRONG_LENGTH); + goto err; + } + *pval = (ASN1_VALUE *)ASN1_NULL_new(); + break; + + case V_ASN1_BOOLEAN: + if(plen != 1) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); + goto err; + } + tbool = (int *)pval; + *tbool = *cont; + break; + + case V_ASN1_BIT_STRING: + if(!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) goto err; + break; + + case V_ASN1_INTEGER: + case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_NEG_ENUMERATED: + if(!c2i_ASN1_INTEGER((ASN1_INTEGER **)pval, &cont, len)) goto err; + break; + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + /* All based on ASN1_STRING and handled the same */ + if(!*pval) { + stmp = ASN1_STRING_type_new(utype); + if(!stmp) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else stmp = (ASN1_STRING *)*pval; + /* If we've already allocated a buffer use it */ + if(cst) { + if(stmp->data) OPENSSL_free(stmp->data); + stmp->data = cont; + stmp->length = len; + buf.data = NULL; + } else { + if(!ASN1_STRING_set(stmp, cont, len)) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + } + break; + + /* If SEQUENCE, or SET or we don't understand the type + * then just collect its encoded form + */ + + default: + case V_ASN1_SET: + case V_ASN1_SEQUENCE: + if(!*pval) { + stmp = ASN1_STRING_new(); + if(!stmp) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + goto err; + } + *pval = (ASN1_VALUE *)stmp; + } else stmp = (ASN1_STRING *)*pval; + if(!ASN1_STRING_set(stmp, *in, inlen)) { + ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(stmp); + *pval = NULL; + goto err; + } + break; + + } + + *in = p; + ret = 1; + err: + if(cst && buf.data) OPENSSL_free(buf.data); + return ret; +} + +/* This function collects the asn1 data from a constructred string + * type into a buffer. The values of 'in' and 'len' should refer + * to the contents of the constructed type and 'inf' should be set + * if it is indefinite length + */ + +static int asn1_collect(BUF_MEM *buf, unsigned char **in, long len, char inf, int tag) +{ + unsigned char *p, *q; + long plen; + char cst; + p = *in; + inf &= 1; + while(len > 0) { + q = p; + /* Check for EOC */ + if(asn1_check_eoc(&p, len)) { + /* EOC is illegal outside indefinite length constructed form */ + if(!inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); + return 0; + } + inf = 0; + goto err; + } + if(!asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, &p, len, tag, V_ASN1_UNIVERSAL, 0, NULL)) { + ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); + return 0; + } + /* If indefinite length constructed update max length */ + if(cst) { + if(!asn1_collect(buf, &p, plen, inf, tag)) return 0; + } else { + if(!collect_data(buf, &p, plen)) return 0; + } + len -= p - q; + } + if(inf) { + ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); + return 0; + } + *in = p; + return 1; + err: + return 0; +} + +static int collect_data(BUF_MEM *buf, unsigned char **p, long plen) +{ + int len; + len = buf->length; + if(!BUF_MEM_grow(buf, len + plen)) { + ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(buf->data + len, *p, plen); + *p += plen; + return 1; +} + +/* Check for ASN1 EOC and swallow it if found */ + +static int asn1_check_eoc(unsigned char **in, long len) +{ + unsigned char *p; + if(len < 2) return 0; + p = *in; + if(!p[0] && !p[1]) { + *in += 2; + return 1; + } + return 0; +} + +/* Check an ASN1 tag and length: a bit like ASN1_get_object + * but it sets the length for indefinite length constructed + * form, we don't know the exact length but we can set an + * upper bound to the amount of data available minus the + * header length just read. + */ + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf, char *cst, + unsigned char **in, long len, int exptag, int expclass, char opt, ASN1_TLC *ctx) +{ + int i; + int ptag, pclass; + long plen; + unsigned char *p, *q; + p = *in; + q = p; + + if(ctx && ctx->valid) { + i = ctx->ret; + plen = ctx->plen; + pclass = ctx->pclass; + ptag = ctx->ptag; + p += ctx->hdrlen; + } else { + i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); + if(ctx) { + ctx->ret = i; + ctx->plen = plen; + ctx->pclass = pclass; + ctx->ptag = ptag; + ctx->hdrlen = p - q; + ctx->valid = 1; + } + } + + if(i & 0x80) { + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); + asn1_tlc_clear(ctx); + return 0; + } + if(exptag >= 0) { + if((exptag != ptag) || (expclass != pclass)) { + /* If type is OPTIONAL, not an error, but indicate missing + * type. + */ + if(opt) return -1; + asn1_tlc_clear(ctx); + ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); + return 0; + } + /* We have a tag and class match, so assume we are going to do something with it */ + asn1_tlc_clear(ctx); + } + if(i & 1) plen = len - (p - q); + + if(inf) *inf = i & 1; + + if(cst) *cst = i & V_ASN1_CONSTRUCTED; + + if(olen) *olen = plen; + if(oclass) *oclass = pclass; + if(otag) *otag = ptag; + + *in = p; + return 1; +} + + + diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c new file mode 100644 index 000000000..81f35db97 --- /dev/null +++ b/crypto/asn1/tasn_enc.c @@ -0,0 +1,415 @@ +/* tasn_enc.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> + +static int asn1_i2d_ex_primitive(ASN1_VALUE *val, unsigned char **out, int utype, int tag, int aclass); +static int asn1_set_seq_out(STACK *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset); + +/* Encode an ASN1 item, this currently behaves just + * like a standard 'i2d' function. 'out' points to + * a buffer to output the data to, in future we will + * have more advanced versions that can output data + * a piece at a time and this will simply be a special + * case. + */ + + +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +{ + return ASN1_item_ex_i2d(val, out, it, -1, 0); +} + +/* Encode an item, taking care of IMPLICIT tagging (if any). + * This function performs the normal item handling: it can be + * used in external types. + */ + +int ASN1_item_ex_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) +{ + const ASN1_TEMPLATE *tt = NULL; + unsigned char *p = NULL; + int i, seqcontlen, seqlen; + ASN1_STRING *strtmp; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + if(!val) return 0; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + return ASN1_template_i2d(val, out, it->templates); + return asn1_i2d_ex_primitive(val, out, it->utype, tag, aclass); + break; + + case ASN1_ITYPE_MSTRING: + strtmp = (ASN1_STRING *)val; + return asn1_i2d_ex_primitive(val, out, strtmp->type, tag, aclass); + + case ASN1_ITYPE_CHOICE: + i = asn1_get_choice_selector(val, it); + if((i >= 0) && (i < it->tcount)) { + ASN1_VALUE *chval; + const ASN1_TEMPLATE *chtt; + chtt = it->templates + i; + chval = asn1_get_field(val, chtt); + return ASN1_template_i2d(chval, out, chtt); + } + /* Fixme: error condition if selector out of range */ + break; + + case ASN1_ITYPE_EXTERN: + /* If new style i2d it does all the work */ + ef = it->funcs; + return ef->asn1_ex_i2d(val, out, it, tag, aclass); + + case ASN1_ITYPE_COMPAT: + /* old style hackery... */ + cf = it->funcs; + if(out) p = *out; + i = cf->asn1_i2d(val, out); + /* Fixup for IMPLICIT tag: note this messes up for tags > 30, + * but so did the old code. Tags > 30 are very rare anyway. + */ + if(out && (tag != -1)) + *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED); + return i; + + case ASN1_ITYPE_SEQUENCE: + seqcontlen = 0; + /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ + if(tag == -1) { + tag = V_ASN1_SEQUENCE; + aclass = V_ASN1_UNIVERSAL; + } + /* First work out sequence content length */ + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE *seqval; + seqtt = asn1_do_adb(val, tt); + if(!seqtt) return 0; + seqval = asn1_get_field(val, seqtt); + /* FIXME: check for errors in enhanced version */ + /* FIXME: special handling of indefinite length encoding */ + seqcontlen += ASN1_template_i2d(seqval, NULL, seqtt); + } + seqlen = ASN1_object_size(1, seqcontlen, tag); + if(!out) return seqlen; + /* Output SEQUENCE header */ + ASN1_put_object(out, 1, seqcontlen, tag, aclass); + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + const ASN1_TEMPLATE *seqtt; + ASN1_VALUE *seqval; + seqtt = asn1_do_adb(val, tt); + if(!seqtt) return 0; + seqval = asn1_get_field(val, seqtt); + /* FIXME: check for errors in enhanced version */ + ASN1_template_i2d(seqval, out, seqtt); + } + return seqlen; + + default: + return 0; + } + return 0; +} + +int ASN1_template_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_TEMPLATE *tt) +{ + int i, ret, flags, aclass; + if(!val) return 0; + flags = tt->flags; + aclass = flags & ASN1_TFLG_TAG_CLASS; + if(flags & ASN1_TFLG_SK_MASK) { + /* SET OF, SEQUENCE OF */ + STACK *sk = (STACK *)val; + int isset, sktag, skaclass; + int skcontlen, sklen; + ASN1_VALUE *skitem; + isset = flags & ASN1_TFLG_SET_OF; + /* First work out inner tag value */ + if(flags & ASN1_TFLG_IMPTAG) { + sktag = tt->tag; + skaclass = aclass; + } else { + skaclass = V_ASN1_UNIVERSAL; + if(isset) sktag = V_ASN1_SET; + else sktag = V_ASN1_SEQUENCE; + } + /* Now work out length of items */ + skcontlen = 0; + for(i = 0; i < sk_num(sk); i++) { + skitem = (ASN1_VALUE *)sk_value(sk, i); + skcontlen += ASN1_item_ex_i2d(skitem, NULL, tt->item, -1, 0); + } + sklen = ASN1_object_size(1, skcontlen, sktag); + /* If EXPLICIT need length of surrounding tag */ + if(flags & ASN1_TFLG_EXPTAG) + ret = ASN1_object_size(1, sklen, tt->tag); + else ret = sklen; + + if(!out) return ret; + + /* Now encode this lot... */ + /* EXPLICIT tag */ + if(flags & ASN1_TFLG_EXPTAG) + ASN1_put_object(out, 1, sklen, tt->tag, aclass); + /* SET or SEQUENCE and IMPLICIT tag */ + ASN1_put_object(out, 1, skcontlen, sktag, skaclass); + /* And finally the stuff itself */ + asn1_set_seq_out(sk, out, skcontlen, tt->item, isset); + + return ret; + } + + if(flags & ASN1_TFLG_EXPTAG) { + /* EXPLICIT tagging */ + /* Find length of tagged item */ + i = ASN1_item_ex_i2d(val, NULL, tt->item, -1, 0); + /* Find length of EXPLICIT tag */ + ret = ASN1_object_size(1, i, tt->tag); + if(out) { + /* Output tag and item */ + ASN1_put_object(out, 1, i, tt->tag, aclass); + ASN1_item_ex_i2d(val, out, tt->item, -1, 0); + } + return ret; + } + if(flags & ASN1_TFLG_IMPTAG) { + /* IMPLICIT tagging */ + return ASN1_item_ex_i2d(val, out, tt->item, tt->tag, aclass); + } + /* Nothing special: treat as normal */ + return ASN1_item_ex_i2d(val, out, tt->item, -1, 0); +} + +/* Temporary structure used to hold DER encoding of items for SET OF */ + +typedef struct { + unsigned char *data; + int length; +} DER_ENC; + +static int der_cmp(const void *a, const void *b) +{ + const DER_ENC *d1 = a, *d2 = b; + int cmplen, i; + cmplen = (d1->length < d2->length) ? d1->length : d2->length; + i = memcmp(d1->data, d2->data, cmplen); + if(i) return i; + return d1->length - d2->length; +} + +/* Output the content octets of SET OF or SEQUENCE OF */ + +static int asn1_set_seq_out(STACK *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort) +{ + int i; + void *skitem; + unsigned char *tmpdat, *p; + DER_ENC *derlst, *tder; + if(do_sort) { + /* Don't need to sort less than 2 items */ + if(sk_num(sk) < 2) do_sort = 0; + else { + derlst = OPENSSL_malloc(sk_num(sk) * sizeof(*derlst)); + tmpdat = OPENSSL_malloc(skcontlen); + if(!derlst || !tmpdat) return 0; + } + } + /* If not sorting just output each item */ + if(!do_sort) { + for(i = 0; i < sk_num(sk); i++) { + skitem = sk_value(sk, i); + ASN1_item_i2d(skitem, out, item); + } + return 1; + } + p = tmpdat; + /* Doing sort: build up a list of each member's DER encoding */ + for(i = 0, tder = derlst; i < sk_num(sk); i++, tder++) { + skitem = sk_value(sk, i); + tder->data = p; + tder->length = ASN1_item_i2d(skitem, &p, item); + } + /* Now sort them */ + qsort(derlst, sk_num(sk), sizeof(*derlst), der_cmp); + /* Output sorted DER encoding */ + p = *out; + for(i = 0, tder = derlst; i < sk_num(sk); i++, tder++) { + memcpy(p, tder->data, tder->length); + p += tder->length; + } + *out = p; + OPENSSL_free(derlst); + OPENSSL_free(tmpdat); + return 1; +} + +static int asn1_i2d_ex_primitive(ASN1_VALUE *val, unsigned char **out, int utype, int tag, int aclass) +{ + int len; + unsigned char *cont = NULL, c; + ASN1_OBJECT *otmp; + ASN1_STRING *stmp; + int btmp; + if(!val) return 0; + if(utype == V_ASN1_ANY) { + ASN1_TYPE *atype; + atype = (ASN1_TYPE *)val; + utype = atype->type; + /* NB: not a leak because ASN1_NULL_new() + * doesn't allocate anything + */ + if(utype == V_ASN1_NULL) val = (ASN1_VALUE *)ASN1_NULL_new(); + else val = (ASN1_VALUE *)atype->value.ptr; + } + if(tag == -1) { + tag = utype; + aclass = V_ASN1_UNIVERSAL; + } + /* Setup cont and len to point to content octets and + * their length. + */ + switch(utype) { + case V_ASN1_OBJECT: + otmp = (ASN1_OBJECT *)val; + cont = otmp->data; + len = otmp->length; + break; + + case V_ASN1_NULL: + cont = NULL; + len = 0; + break; + + case V_ASN1_BOOLEAN: + btmp = *(int *)val; + /* -1 means undefined and thus omitted */ + if(btmp == -1) return 0; + if(btmp) c = 0xff; + else c = 0; + cont = &c; + len = 1; + break; + + case V_ASN1_BIT_STRING: + len = i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)val, NULL); + if(out) { + ASN1_put_object(out, 0, len, tag, aclass); + i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)val, out); + } + return ASN1_object_size(0, len, tag); + break; + + case V_ASN1_INTEGER: + case V_ASN1_NEG_INTEGER: + case V_ASN1_ENUMERATED: + case V_ASN1_NEG_ENUMERATED: + /* These are all have the same content format + * as ASN1_INTEGER + */ + len = i2c_ASN1_INTEGER((ASN1_INTEGER *)val, NULL); + if(out) { + ASN1_put_object(out, 0, len, tag, aclass); + i2c_ASN1_INTEGER((ASN1_INTEGER *)val, out); + } + return ASN1_object_size(0, len, tag); + + case V_ASN1_OCTET_STRING: + case V_ASN1_NUMERICSTRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_VIDEOTEXSTRING: + case V_ASN1_IA5STRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_VISIBLESTRING: + case V_ASN1_GENERALSTRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_BMPSTRING: + case V_ASN1_UTF8STRING: + /* All based on ASN1_STRING and handled the same */ + stmp = (ASN1_STRING *)val; + cont = stmp->data; + len = stmp->length; + + break; + + + case V_ASN1_SEQUENCE: + case V_ASN1_SET: + default: + stmp = (ASN1_STRING *)val; + if(stmp->data && out) memcpy(*out, stmp->data, stmp->length); + return stmp->length; + + } + if(out) { + ASN1_put_object(out, 0, len, tag, aclass); + if(cont) memcpy(*out, cont, len); + *out += len; + } + return ASN1_object_size(0, len, tag); +} diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c new file mode 100644 index 000000000..3f1a764d0 --- /dev/null +++ b/crypto/asn1/tasn_fre.c @@ -0,0 +1,152 @@ +/* tasn_fre.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> + +/* Free up an ASN1 structure */ + +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) +{ + const ASN1_TEMPLATE *tt = NULL, *seqtt; + const ASN1_EXTERN_FUNCS *ef; + const ASN1_COMPAT_FUNCS *cf; + int i; + if(!val) return; + + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + ASN1_primitive_free(val, it->utype); + break; + + case ASN1_ITYPE_MSTRING: + ASN1_primitive_free(val, -1); + break; + + case ASN1_ITYPE_CHOICE: + i = asn1_get_choice_selector(val, it); + if((i >= 0) && (i < it->tcount)) { + ASN1_VALUE *chval; + tt = it->templates + i; + chval = asn1_get_field(val, tt); + ASN1_template_free(chval, tt); + } + OPENSSL_free(val); + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if(cf && cf->asn1_free) cf->asn1_free(val); + break; + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if(ef && ef->asn1_ex_free) ef->asn1_ex_free(val, it); + break; + + case ASN1_ITYPE_SEQUENCE: + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + ASN1_VALUE *seqval; + seqtt = asn1_do_adb(val, tt); + seqval = asn1_get_field(val, seqtt); + ASN1_template_free(seqval, seqtt); + } + OPENSSL_free(val); + break; + } +} + +void ASN1_template_free(ASN1_VALUE *val, const ASN1_TEMPLATE *tt) +{ + int i; + if(tt->flags & ASN1_TFLG_SK_MASK) { + STACK *sk = (STACK *)val; + for(i = 0; i < sk_num(sk); i++) { + ASN1_item_free((ASN1_VALUE *)sk_value(sk, i), tt->item); + } + sk_free(sk); + } else ASN1_item_free(val, tt->item); +} + +void ASN1_primitive_free(ASN1_VALUE *type, long utype) +{ + switch(utype) { + case V_ASN1_OBJECT: + ASN1_OBJECT_free((ASN1_OBJECT *)type); + break; + + case V_ASN1_NULL: + ASN1_NULL_free((ASN1_NULL *)type); + break; + + case V_ASN1_ANY: + ASN1_TYPE_free((ASN1_TYPE *)type); + break; + + case V_ASN1_BOOLEAN: + break; + + default: + ASN1_STRING_free((ASN1_STRING*)type); + break; + } +} diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c new file mode 100644 index 000000000..a1aa9ba0d --- /dev/null +++ b/crypto/asn1/tasn_new.c @@ -0,0 +1,187 @@ +/* tasn_new.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/objects.h> +#include <openssl/err.h> +#include <openssl/asn1t.h> + +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) +{ + ASN1_VALUE *ret = NULL; + if(ASN1_item_ex_new(&ret, it) > 0) return ret; + return NULL; +} + +/* Allocate an ASN1 structure */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + const ASN1_TEMPLATE *tt = NULL; + const ASN1_COMPAT_FUNCS *cf; + const ASN1_EXTERN_FUNCS *ef; + ASN1_VALUE **pseqval; + int i; + + switch(it->itype) { + + case ASN1_ITYPE_EXTERN: + ef = it->funcs; + if(ef && ef->asn1_ex_new) { + if(!ef->asn1_ex_new(pval, it)) + goto memerr; + } + break; + + case ASN1_ITYPE_COMPAT: + cf = it->funcs; + if(cf && cf->asn1_new) { + *pval = cf->asn1_new(); + if(!*pval) goto memerr; + } + break; + + case ASN1_ITYPE_PRIMITIVE: + + if(!ASN1_primitive_new(pval, it->utype)) + goto memerr; + break; + + case ASN1_ITYPE_MSTRING: + if(!ASN1_primitive_new(pval, -1)) + goto memerr; + break; + + case ASN1_ITYPE_CHOICE: + case ASN1_ITYPE_SEQUENCE: + *pval = OPENSSL_malloc(it->size); + if(!*pval) goto memerr; + memset(*pval, 0, it->size); + /* FIXME: set selector for CHOICE */ + for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) { + pseqval = asn1_get_field_ptr(pval, tt); + if(!ASN1_template_new(pseqval, tt)) goto memerr; + } + break; + } + return 1; + + memerr: + ASN1err(ASN1_F_ASN1_ITEM_NEW, ERR_R_MALLOC_FAILURE); + return 0; +} + + +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + const ASN1_ITEM *it = tt->item; + /* Special BOOLEAN handling */ + if(asn1_template_is_bool(tt)) + return ASN1_item_ex_new(pval, it); + + /* If OPTIONAL or ANY DEFINED BY nothing to do */ + if(tt->flags & (ASN1_TFLG_OPTIONAL|ASN1_TFLG_ADB_MASK)) { + /* Maybe free it first? */ + *pval = NULL; + return 1; + } + /* If SET OF or SEQUENCE OF, its a STACK */ + if(tt->flags & ASN1_TFLG_SK_MASK) { + *pval = (ASN1_VALUE *)sk_new_null(); + if(!*pval) { + ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; + } + /* Otherwise pass it back to the item routine */ + return ASN1_item_ex_new(pval, it); +} + +/* NB: could probably combine most of the real XXX_new() behaviour and junk all the old + * functions. + */ + +int ASN1_primitive_new(ASN1_VALUE **pval, long utype) +{ + switch(utype) { + case V_ASN1_OBJECT: + *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); + return 1; + + case V_ASN1_BOOLEAN: + *(int *)pval = -1; + return 1; + + case V_ASN1_NULL: + *pval = (ASN1_VALUE *)ASN1_NULL_new(); + return 1; + + case V_ASN1_ANY: + *pval = (ASN1_VALUE *)ASN1_TYPE_new(); + break; + + default: + *pval = (ASN1_VALUE *)ASN1_STRING_type_new(utype); + break; + } + if(*pval) return 1; + return 0; +} diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c new file mode 100644 index 000000000..a0c71ea99 --- /dev/null +++ b/crypto/asn1/tasn_prn.c @@ -0,0 +1,196 @@ +/* tasn_prn.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/err.h> +#include <openssl/nasn.h> + +/* Print routines. Print out a whole structure from a template. + */ + +static int asn1_item_print_nm(BIO *out, void *fld, int indent, const ASN1_ITEM *it, const char *name); + +int ASN1_item_print(BIO *out, void *fld, int indent, const ASN1_ITEM *it) +{ + return asn1_item_print_nm(out, fld, indent, it, it->sname); +} + +static int asn1_item_print_nm(BIO *out, void *fld, int indent, const ASN1_ITEM *it, const char *name) +{ + ASN1_STRING *str; + const ASN1_TEMPLATE *tt; + void *tmpfld; + int i; + if(!fld) { + BIO_printf(out, "%*s%s ABSENT\n", indent, "", name); + return 1; + } + switch(it->itype) { + + case ASN1_ITYPE_PRIMITIVE: + if(it->templates) + return ASN1_template_print(out, fld, indent, it->templates); + return asn1_primitive_print(out, fld, it->utype, indent, name); + break; + + case ASN1_ITYPE_MSTRING: + str = fld; + return asn1_primitive_print(out, fld, str->type, indent, name); + + case ASN1_ITYPE_EXTERN: + BIO_printf(out, "%*s%s:EXTERNAL TYPE %s %s\n", indent, "", name, it->sname, fld ? "" : "ABSENT"); + return 1; + case ASN1_ITYPE_COMPAT: + BIO_printf(out, "%*s%s:COMPATIBLE TYPE %s %s\n", indent, "", name, it->sname, fld ? "" : "ABSENT"); + return 1; + + + case ASN1_ITYPE_CHOICE: + /* CHOICE type, get selector */ + i = asn1_get_choice_selector(fld, it); + /* This should never happen... */ + if((i < 0) || (i >= it->tcount)) { + BIO_printf(out, "%s selector [%d] out of range\n", it->sname, i); + return 1; + } + tt = it->templates + i; + tmpfld = asn1_get_field(fld, tt); + return ASN1_template_print(out, tmpfld, indent, tt); + + case ASN1_ITYPE_SEQUENCE: + BIO_printf(out, "%*s%s {\n", indent, "", name); + /* Get each field entry */ + for(i = 0, tt = it->templates; i < it->tcount; i++, tt++) { + tmpfld = asn1_get_field(fld, tt); + ASN1_template_print(out, tmpfld, indent + 2, tt); + } + BIO_printf(out, "%*s}\n", indent, ""); + return 1; + + default: + return 0; + } +} + +int ASN1_template_print(BIO *out, void *fld, int indent, const ASN1_TEMPLATE *tt) +{ + int i, flags; + //if(!fld) return 0; + flags = tt->flags; + if(flags & ASN1_TFLG_SK_MASK) { + char *tname; + void *skitem; + /* SET OF, SEQUENCE OF */ + if(flags & ASN1_TFLG_SET_OF) tname = "SET"; + else tname = "SEQUENCE"; + if(fld) { + BIO_printf(out, "%*s%s OF %s {\n", indent, "", tname, tt->field_name); + for(i = 0; i < sk_num(fld); i++) { + skitem = sk_value(fld, i); + asn1_item_print_nm(out, skitem, indent + 2, tt->item, ""); + } + BIO_printf(out, "%*s}\n", indent, ""); + } else + BIO_printf(out, "%*s%s OF %s ABSENT\n", indent, "", tname, tt->field_name); + return 1; + } + return asn1_item_print_nm(out, fld, indent, tt->item, tt->field_name); +} + +static int asn1_primitive_print(BIO *out, void *fld, long utype, int indent, const char *name) +{ + ASN1_STRING *str = fld; + if(fld) { + if(utype == V_ASN1_BOOLEAN) { + int *bool = fld; +if(*bool == -1) printf("BOOL MISSING\n"); + BIO_printf(out, "%*s%s:%s", indent, "", "BOOLEAN", *bool ? "TRUE" : "FALSE"); + } else if((utype == V_ASN1_INTEGER) + || (utype == V_ASN1_ENUMERATED)) { + char *s, *nm; + s = i2s_ASN1_INTEGER(NULL, fld); + if(utype == V_ASN1_INTEGER) nm = "INTEGER"; + else nm = "ENUMERATED"; + BIO_printf(out, "%*s%s:%s", indent, "", nm, s); + OPENSSL_free(s); + } else if(utype == V_ASN1_NULL) { + BIO_printf(out, "%*s%s", indent, "", "NULL"); + } else if(utype == V_ASN1_UTCTIME) { + BIO_printf(out, "%*s%s:%s:", indent, "", name, "UTCTIME"); + ASN1_UTCTIME_print(out, str); + } else if(utype == V_ASN1_GENERALIZEDTIME) { + BIO_printf(out, "%*s%s:%s:", indent, "", name, "GENERALIZEDTIME"); + ASN1_GENERALIZEDTIME_print(out, str); + } else if(utype == V_ASN1_OBJECT) { + char objbuf[80], *ln; + ln = OBJ_nid2ln(OBJ_obj2nid(fld)); + if(!ln) ln = ""; + OBJ_obj2txt(objbuf, 80, fld, 1); + BIO_printf(out, "%*s%s:%s (%s)", indent, "", "OBJECT", ln, objbuf); + } else { + BIO_printf(out, "%*s%s:", indent, "", name); + ASN1_STRING_print_ex(out, str, ASN1_STRFLGS_DUMP_UNKNOWN|ASN1_STRFLGS_SHOW_TYPE); + } + BIO_printf(out, "\n"); + } else BIO_printf(out, "%*s%s [ABSENT]\n", indent, "", name); + return 1; +} diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c new file mode 100644 index 000000000..c5ba39301 --- /dev/null +++ b/crypto/asn1/tasn_typ.c @@ -0,0 +1,84 @@ +/* tasn_typ.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stdio.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> + + + +#define IMPLEMENT_ASN1_TYPE(type) const ASN1_ITEM type##_it = { ASN1_ITYPE_PRIMITIVE, V_##type, NULL, 0, NULL, sizeof(type)} + + +IMPLEMENT_ASN1_TYPE(ASN1_BOOLEAN); +IMPLEMENT_ASN1_TYPE(ASN1_INTEGER); +IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING); +IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING); +IMPLEMENT_ASN1_TYPE(ASN1_NULL); +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT); +IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED); +IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING); +IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING); +IMPLEMENT_ASN1_TYPE(ASN1_T61STRING); +IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING); +IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME); +IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME); +IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING); +IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING); +IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING); +const ASN1_ITEM ASN1_ANY_it = { ASN1_ITYPE_PRIMITIVE, V_ASN1_ANY, NULL, 0, NULL, sizeof(ASN1_TYPE)}; + diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c new file mode 100644 index 000000000..7068a0284 --- /dev/null +++ b/crypto/asn1/tasn_utl.c @@ -0,0 +1,185 @@ +/* tasn_utl.c */ +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 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 <stddef.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> + +/* Utility functions for manipulating fields and offsets */ + +/* Add 'offset' to 'addr' */ +#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset) + +/* Given an ASN1_ITEM CHOICE type return + * the selector value + */ + +int asn1_get_choice_selector(ASN1_VALUE *val, const ASN1_ITEM *it) +{ + int *sel = offset2ptr(val, it->utype); + return *sel; +} + +/* Given an ASN1_ITEM CHOICE type set + * the selector value, return old value. + */ + +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it) +{ + int *sel, ret; + sel = offset2ptr(*pval, it->utype); + ret = *sel; + *sel = value; + return ret; +} + +/* Given an ASN1_TEMPLATE get a field */ + +ASN1_VALUE *asn1_get_field(ASN1_VALUE *val, const ASN1_TEMPLATE *tt) +{ + ASN1_VALUE **ptr = offset2ptr(val, tt->offset); + /* NOTE for BOOLEAN types the field is just a plain + * int so we don't dereference it. This means that + * BOOLEAN is an (int *). + */ + if(asn1_template_is_bool(tt)) { + int *bool = (int *)ptr; + /* If BOOLEAN is -1 it is absent so return + * NULL for compatibility with other types + */ + if(*bool == -1) + return NULL; + return (ASN1_VALUE *)ptr; + } + return *ptr; +} + +/* Given an ASN1_TEMPLATE get a pointer to a field */ +ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ + ASN1_VALUE **pvaltmp = offset2ptr(*pval, tt->offset); + /* NOTE for BOOLEAN types the field is just a plain + * int so we can't return int **, so settle for + * (int *). + */ + return pvaltmp; +} + +/* Handle ANY DEFINED BY template, find the selector, look up + * the relevant ASN1_TEMPLATE in the table and return it. + */ + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE *val, const ASN1_TEMPLATE *tt) +{ + const ASN1_ADB *adb; + const ASN1_ADB_TABLE *atbl; + long selector; + ASN1_VALUE *sfld; + int i; + if(!(tt->flags & ASN1_TFLG_ADB_MASK)) return tt; + + /* Else ANY DEFINED BY ... get the table */ + adb = tt->item; + + /* Get the selector field */ + sfld = offset2ptr(val, adb->offset); + + /* Check if NULL */ + if(!sfld) return adb->null_tt; + + /* Convert type to a long: + * NB: don't check for NID_undef here because it + * might be a legitimate value in the table + */ + if(tt->flags & ASN1_TFLG_ADB_OID) + selector = OBJ_obj2nid((ASN1_OBJECT *)sfld); + else + selector = ASN1_INTEGER_get((ASN1_INTEGER *)sfld); + + /* Try to find matching entry in table + * Maybe should check application types first to + * allow application override? Might also be useful + * to have a flag which indicates table is sorted and + * we can do a binary search. For now stick to a + * linear search. + */ + + for(atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) + if(atbl->value == selector) return atbl->tt; + + /* FIXME: need to search application table too */ + + /* No match, return default type */ + return adb->default_tt; +} + +int asn1_template_is_bool(const ASN1_TEMPLATE *tt) +{ + if(tt->flags & ASN1_TFLG_SK_MASK) return 0; + else return asn1_item_is_bool(tt->item); +} + +int asn1_item_is_bool(const ASN1_ITEM *it) +{ + /* Special BOOLEAN handling */ + if((it->utype == V_ASN1_BOOLEAN) && + (it->itype == ASN1_ITYPE_PRIMITIVE)) return 1; + return 0; +} |