aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asn1
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2008-03-12 21:14:28 +0000
committerDr. Stephen Henson <steve@openssl.org>2008-03-12 21:14:28 +0000
commit8931b30d8478b0bd24af251fac64e7b0bf121369 (patch)
tree04d17028c745633b40b997699bc580c7b4cc600d /crypto/asn1
parent27dc105f51361fc71f556e927f621218883b0c26 (diff)
downloadopenssl-8931b30d8478b0bd24af251fac64e7b0bf121369.tar.gz
And so it begins...
Initial support for CMS. Add zlib compression BIO. Add AES key wrap implementation. Generalize S/MIME MIME code to support CMS and/or PKCS7.
Diffstat (limited to 'crypto/asn1')
-rw-r--r--crypto/asn1/Makefile59
-rw-r--r--crypto/asn1/asn1.h53
-rw-r--r--crypto/asn1/asn1_err.c20
-rw-r--r--crypto/asn1/asn1t.h29
-rw-r--r--crypto/asn1/asn_mime.c938
-rw-r--r--crypto/asn1/bio_ndef.c246
-rw-r--r--crypto/asn1/p5_pbe.c105
-rw-r--r--crypto/asn1/x_algor.c5
8 files changed, 1395 insertions, 60 deletions
diff --git a/crypto/asn1/Makefile b/crypto/asn1/Makefile
index 8ec745b8c5..4b4da3decf 100644
--- a/crypto/asn1/Makefile
+++ b/crypto/asn1/Makefile
@@ -27,7 +27,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \
tasn_prn.c ameth_lib.c \
f_int.c f_string.c n_pkey.c \
- f_enum.c x_pkey.c a_bool.c x_exten.c bio_asn1.c \
+ f_enum.c x_pkey.c a_bool.c x_exten.c bio_asn1.c bio_ndef.c asn_mime.c \
asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_bytes.c a_strnid.c \
evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c asn_moid.c
LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
@@ -40,7 +40,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
tasn_new.o tasn_fre.o tasn_enc.o tasn_dec.o tasn_utl.o tasn_typ.o \
tasn_prn.o ameth_lib.o \
f_int.o f_string.o n_pkey.o \
- f_enum.o x_pkey.o a_bool.o x_exten.o bio_asn1.o \
+ f_enum.o x_pkey.o a_bool.o x_exten.o bio_asn1.o bio_ndef.o asn_mime.o \
asn1_gen.o asn1_par.o asn1_lib.o asn1_err.o a_bytes.o a_strnid.o \
evp_asn1.o asn_pack.o p5_pbe.o p5_pbev2.o p8_pkey.o asn_moid.o
@@ -366,6 +366,20 @@ asn1_par.o: ../../include/openssl/opensslconf.h
asn1_par.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
asn1_par.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
asn1_par.o: ../../include/openssl/symhacks.h ../cryptlib.h asn1_par.c
+asn_mime.o: ../../e_os.h ../../include/openssl/asn1.h
+asn_mime.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
+asn_mime.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+asn_mime.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+asn_mime.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+asn_mime.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+asn_mime.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+asn_mime.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+asn_mime.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+asn_mime.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
+asn_mime.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+asn_mime.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+asn_mime.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+asn_mime.o: ../cryptlib.h asn1_locl.h asn_mime.c
asn_moid.o: ../../e_os.h ../../include/openssl/asn1.h
asn_moid.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
asn_moid.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
@@ -394,16 +408,26 @@ bio_asn1.o: ../../include/openssl/opensslconf.h
bio_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
bio_asn1.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
bio_asn1.o: ../../include/openssl/symhacks.h bio_asn1.c
+bio_ndef.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+bio_ndef.o: ../../include/openssl/bio.h ../../include/openssl/crypto.h
+bio_ndef.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
+bio_ndef.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h
+bio_ndef.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+bio_ndef.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+bio_ndef.o: ../../include/openssl/symhacks.h bio_ndef.c
d2i_pr.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
d2i_pr.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
d2i_pr.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
-d2i_pr.o: ../../include/openssl/engine.h ../../include/openssl/err.h
-d2i_pr.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
-d2i_pr.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
-d2i_pr.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
-d2i_pr.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
-d2i_pr.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
-d2i_pr.o: ../cryptlib.h asn1_locl.h d2i_pr.c
+d2i_pr.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+d2i_pr.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+d2i_pr.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+d2i_pr.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+d2i_pr.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+d2i_pr.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+d2i_pr.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+d2i_pr.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+d2i_pr.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+d2i_pr.o: ../../include/openssl/x509_vfy.h ../cryptlib.h asn1_locl.h d2i_pr.c
d2i_pu.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
d2i_pu.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
d2i_pu.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h
@@ -447,13 +471,16 @@ f_string.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
f_string.o: ../../include/openssl/symhacks.h ../cryptlib.h f_string.c
i2d_pr.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
i2d_pr.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
-i2d_pr.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
-i2d_pr.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
-i2d_pr.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
-i2d_pr.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
-i2d_pr.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
-i2d_pr.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
-i2d_pr.o: ../cryptlib.h asn1_locl.h i2d_pr.c
+i2d_pr.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+i2d_pr.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+i2d_pr.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+i2d_pr.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+i2d_pr.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+i2d_pr.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+i2d_pr.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+i2d_pr.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+i2d_pr.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+i2d_pr.o: ../../include/openssl/x509_vfy.h ../cryptlib.h asn1_locl.h i2d_pr.c
i2d_pu.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
i2d_pu.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
i2d_pu.o: ../../include/openssl/crypto.h ../../include/openssl/dsa.h
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 8acf94594f..6ab12a9df9 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -158,7 +158,12 @@ extern "C" {
#define MBSTRING_BMP (MBSTRING_FLAG|2)
#define MBSTRING_UNIV (MBSTRING_FLAG|4)
+#define SMIME_OLDMIME 0x400
+#define SMIME_CRLFEOL 0x800
+#define SMIME_STREAM 0x1000
+
struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
@@ -218,6 +223,13 @@ typedef struct asn1_object_st
* be inserted in the memory buffer
*/
#define ASN1_STRING_FLAG_NDEF 0x010
+
+/* This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been
+ * accessed. The flag will be reset when content has been written to it.
+ */
+
+#define ASN1_STRING_FLAG_CONT 0x020
/* This is the base type that holds just about everything :-) */
typedef struct asn1_string_st
{
@@ -939,6 +951,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+ ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
#ifndef OPENSSL_NO_FP_API
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
@@ -1100,6 +1118,21 @@ void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
BIO_METHOD *BIO_f_asn1(void);
+BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
+
+int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const ASN1_ITEM *it);
+int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const char *hdr,
+ const ASN1_ITEM *it);
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid,
+ STACK_OF(X509_ALGOR) *mdalgs,
+ const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_asn1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
+int SMIME_text(BIO *in, BIO *out);
+
/* 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.
@@ -1149,6 +1182,7 @@ void ERR_load_ASN1_strings(void);
#define ASN1_F_ASN1_ITEM_VERIFY 197
#define ASN1_F_ASN1_MBSTRING_NCOPY 122
#define ASN1_F_ASN1_OBJECT_NEW 123
+#define ASN1_F_ASN1_OUTPUT_DATA 214
#define ASN1_F_ASN1_PACK_STRING 124
#define ASN1_F_ASN1_PCTX_NEW 205
#define ASN1_F_ASN1_PKCS5_PBE_SET 125
@@ -1168,6 +1202,9 @@ void ERR_load_ASN1_strings(void);
#define ASN1_F_ASN1_UNPACK_STRING 136
#define ASN1_F_ASN1_UTCTIME_SET 187
#define ASN1_F_ASN1_VERIFY 137
+#define ASN1_F_B64_READ_ASN1 209
+#define ASN1_F_B64_WRITE_ASN1 210
+#define ASN1_F_BIO_NEW_NDEF 208
#define ASN1_F_BITSTR_CB 180
#define ASN1_F_BN_TO_ASN1_ENUMERATED 138
#define ASN1_F_BN_TO_ASN1_INTEGER 139
@@ -1196,6 +1233,7 @@ void ERR_load_ASN1_strings(void);
#define ASN1_F_D2I_X509 156
#define ASN1_F_D2I_X509_CINF 157
#define ASN1_F_D2I_X509_PKEY 159
+#define ASN1_F_I2D_ASN1_BIO_STREAM 211
#define ASN1_F_I2D_ASN1_SET 188
#define ASN1_F_I2D_ASN1_TIME 160
#define ASN1_F_I2D_DSA_PUBKEY 161
@@ -1209,6 +1247,9 @@ void ERR_load_ASN1_strings(void);
#define ASN1_F_PARSE_TAGGING 182
#define ASN1_F_PKCS5_PBE2_SET_IV 167
#define ASN1_F_PKCS5_PBE_SET 202
+#define ASN1_F_PKCS5_PBE_SET0_ALGOR 215
+#define ASN1_F_SMIME_READ_ASN1 212
+#define ASN1_F_SMIME_TEXT 213
#define ASN1_F_X509_CINF_NEW 168
#define ASN1_F_X509_CRL_ADD0_REVOKED 169
#define ASN1_F_X509_INFO_NEW 170
@@ -1220,6 +1261,8 @@ void ERR_load_ASN1_strings(void);
/* Reason codes. */
#define ASN1_R_ADDING_OBJECT 171
+#define ASN1_R_ASN1_PARSE_ERROR 203
+#define ASN1_R_ASN1_SIG_PARSE_ERROR 204
#define ASN1_R_AUX_ERROR 100
#define ASN1_R_BAD_CLASS 101
#define ASN1_R_BAD_OBJECT_HEADER 102
@@ -1267,6 +1310,7 @@ void ERR_load_ASN1_strings(void);
#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128
#define ASN1_R_INVALID_BMPSTRING_LENGTH 129
#define ASN1_R_INVALID_DIGIT 130
+#define ASN1_R_INVALID_MIME_TYPE 205
#define ASN1_R_INVALID_MODIFIER 186
#define ASN1_R_INVALID_NUMBER 187
#define ASN1_R_INVALID_SEPARATOR 131
@@ -1276,6 +1320,9 @@ void ERR_load_ASN1_strings(void);
#define ASN1_R_IV_TOO_LARGE 135
#define ASN1_R_LENGTH_ERROR 136
#define ASN1_R_LIST_ERROR 188
+#define ASN1_R_MIME_NO_CONTENT_TYPE 206
+#define ASN1_R_MIME_PARSE_ERROR 207
+#define ASN1_R_MIME_SIG_PARSE_ERROR 208
#define ASN1_R_MISSING_EOC 137
#define ASN1_R_MISSING_SECOND_NUMBER 138
#define ASN1_R_MISSING_VALUE 189
@@ -1285,8 +1332,12 @@ void ERR_load_ASN1_strings(void);
#define ASN1_R_NON_HEX_CHARACTERS 141
#define ASN1_R_NOT_ASCII_FORMAT 190
#define ASN1_R_NOT_ENOUGH_DATA 142
+#define ASN1_R_NO_CONTENT_TYPE 209
#define ASN1_R_NO_DEFAULT_DIGEST 201
#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE 210
+#define ASN1_R_NO_MULTIPART_BOUNDARY 211
+#define ASN1_R_NO_SIG_CONTENT_TYPE 212
#define ASN1_R_NULL_IS_WRONG_LENGTH 144
#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191
#define ASN1_R_ODD_NUMBER_OF_CHARS 145
@@ -1296,6 +1347,8 @@ void ERR_load_ASN1_strings(void);
#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149
#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192
#define ASN1_R_SHORT_LINE 150
+#define ASN1_R_SIG_INVALID_MIME_TYPE 213
+#define ASN1_R_STREAMING_NOT_SUPPORTED 202
#define ASN1_R_STRING_TOO_LONG 151
#define ASN1_R_STRING_TOO_SHORT 152
#define ASN1_R_TAG_VALUE_TOO_HIGH 153
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index 480ed70764..063d705556 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -110,6 +110,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"},
{ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
{ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW), "ASN1_OBJECT_new"},
+{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA), "ASN1_OUTPUT_DATA"},
{ERR_FUNC(ASN1_F_ASN1_PACK_STRING), "ASN1_pack_string"},
{ERR_FUNC(ASN1_F_ASN1_PCTX_NEW), "ASN1_PCTX_new"},
{ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET), "ASN1_PKCS5_PBE_SET"},
@@ -129,6 +130,9 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING), "ASN1_unpack_string"},
{ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET), "ASN1_UTCTIME_set"},
{ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"},
+{ERR_FUNC(ASN1_F_B64_READ_ASN1), "B64_READ_ASN1"},
+{ERR_FUNC(ASN1_F_B64_WRITE_ASN1), "B64_WRITE_ASN1"},
+{ERR_FUNC(ASN1_F_BIO_NEW_NDEF), "BIO_new_NDEF"},
{ERR_FUNC(ASN1_F_BITSTR_CB), "BITSTR_CB"},
{ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED), "BN_to_ASN1_ENUMERATED"},
{ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER), "BN_to_ASN1_INTEGER"},
@@ -157,6 +161,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_FUNC(ASN1_F_D2I_X509), "D2I_X509"},
{ERR_FUNC(ASN1_F_D2I_X509_CINF), "D2I_X509_CINF"},
{ERR_FUNC(ASN1_F_D2I_X509_PKEY), "d2i_X509_PKEY"},
+{ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"},
{ERR_FUNC(ASN1_F_I2D_ASN1_SET), "i2d_ASN1_SET"},
{ERR_FUNC(ASN1_F_I2D_ASN1_TIME), "I2D_ASN1_TIME"},
{ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY), "i2d_DSA_PUBKEY"},
@@ -170,6 +175,9 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_FUNC(ASN1_F_PARSE_TAGGING), "PARSE_TAGGING"},
{ERR_FUNC(ASN1_F_PKCS5_PBE2_SET_IV), "PKCS5_pbe2_set_iv"},
{ERR_FUNC(ASN1_F_PKCS5_PBE_SET), "PKCS5_pbe_set"},
+{ERR_FUNC(ASN1_F_PKCS5_PBE_SET0_ALGOR), "PKCS5_pbe_set0_algor"},
+{ERR_FUNC(ASN1_F_SMIME_READ_ASN1), "SMIME_read_asn1"},
+{ERR_FUNC(ASN1_F_SMIME_TEXT), "SMIME_text"},
{ERR_FUNC(ASN1_F_X509_CINF_NEW), "X509_CINF_NEW"},
{ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED), "X509_CRL_add0_revoked"},
{ERR_FUNC(ASN1_F_X509_INFO_NEW), "X509_INFO_new"},
@@ -184,6 +192,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
static ERR_STRING_DATA ASN1_str_reasons[]=
{
{ERR_REASON(ASN1_R_ADDING_OBJECT) ,"adding object"},
+{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR) ,"asn1 parse error"},
+{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) ,"asn1 sig parse error"},
{ERR_REASON(ASN1_R_AUX_ERROR) ,"aux error"},
{ERR_REASON(ASN1_R_BAD_CLASS) ,"bad class"},
{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER) ,"bad object header"},
@@ -231,6 +241,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),"integer too large for long"},
{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH),"invalid bmpstring length"},
{ERR_REASON(ASN1_R_INVALID_DIGIT) ,"invalid digit"},
+{ERR_REASON(ASN1_R_INVALID_MIME_TYPE) ,"invalid mime type"},
{ERR_REASON(ASN1_R_INVALID_MODIFIER) ,"invalid modifier"},
{ERR_REASON(ASN1_R_INVALID_NUMBER) ,"invalid number"},
{ERR_REASON(ASN1_R_INVALID_SEPARATOR) ,"invalid separator"},
@@ -240,6 +251,9 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ERR_REASON(ASN1_R_IV_TOO_LARGE) ,"iv too large"},
{ERR_REASON(ASN1_R_LENGTH_ERROR) ,"length error"},
{ERR_REASON(ASN1_R_LIST_ERROR) ,"list error"},
+{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) ,"mime no content type"},
+{ERR_REASON(ASN1_R_MIME_PARSE_ERROR) ,"mime parse error"},
+{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) ,"mime sig parse error"},
{ERR_REASON(ASN1_R_MISSING_EOC) ,"missing eoc"},
{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER),"missing second number"},
{ERR_REASON(ASN1_R_MISSING_VALUE) ,"missing value"},
@@ -249,8 +263,12 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) ,"non hex characters"},
{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) ,"not ascii format"},
{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) ,"not enough data"},
+{ERR_REASON(ASN1_R_NO_CONTENT_TYPE) ,"no content type"},
{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST) ,"no default digest"},
{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"},
+{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE) ,"no sig content type"},
{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"},
{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"},
{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS) ,"odd number of chars"},
@@ -260,6 +278,8 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED),"sequence not constructed"},
{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),"sequence or set needs config"},
{ERR_REASON(ASN1_R_SHORT_LINE) ,"short line"},
+{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"},
+{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED),"streaming not supported"},
{ERR_REASON(ASN1_R_STRING_TOO_LONG) ,"string too long"},
{ERR_REASON(ASN1_R_STRING_TOO_SHORT) ,"string too short"},
{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) ,"tag value too high"},
diff --git a/crypto/asn1/asn1t.h b/crypto/asn1/asn1t.h
index fff8030f7d..edf2552cba 100644
--- a/crypto/asn1/asn1t.h
+++ b/crypto/asn1/asn1t.h
@@ -169,6 +169,9 @@ extern "C" {
#define ASN1_NDEF_SEQUENCE(tname) \
ASN1_SEQUENCE(tname)
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+ ASN1_SEQUENCE_cb(tname, cb)
+
#define ASN1_SEQUENCE_cb(tname, cb) \
static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
ASN1_SEQUENCE(tname)
@@ -215,6 +218,18 @@ extern "C" {
#stname \
ASN1_ITEM_end(tname)
+#define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \
+ ;\
+ ASN1_ITEM_start(tname) \
+ ASN1_ITYPE_NDEF_SEQUENCE,\
+ V_ASN1_SEQUENCE,\
+ tname##_seq_tt,\
+ sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\
+ &tname##_aux,\
+ sizeof(stname),\
+ #stname \
+ ASN1_ITEM_end(tname)
+
/* This pair helps declare a CHOICE type. We can do:
*
@@ -720,6 +735,16 @@ typedef struct ASN1_PRINT_ARG_st {
const ASN1_PCTX *pctx;
} ASN1_PRINT_ARG;
+/* For streaming related callbacks exarg points to this structure */
+typedef struct ASN1_STREAM_ARG_st {
+ /* BIO to stream through */
+ BIO *out;
+ /* BIO with filters appended */
+ BIO *ndef_bio;
+ /* Streaming I/O boundary */
+ unsigned char **boundary;
+} ASN1_STREAM_ARG;
+
/* Flags in ASN1_AUX */
/* Use a reference count */
@@ -741,6 +766,10 @@ typedef struct ASN1_PRINT_ARG_st {
#define ASN1_OP_I2D_POST 7
#define ASN1_OP_PRINT_PRE 8
#define ASN1_OP_PRINT_POST 9
+#define ASN1_OP_STREAM_PRE 8
+#define ASN1_OP_STREAM_POST 9
+#define ASN1_OP_DETACHED_PRE 10
+#define ASN1_OP_DETACHED_POST 11
/* Macro to implement a primitive type */
#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0)
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
new file mode 100644
index 0000000000..9148817210
--- /dev/null
+++ b/crypto/asn1/asn_mime.c
@@ -0,0 +1,938 @@
+/* asn_mime.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2008 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.
+ * ====================================================================
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "cryptlib.h"
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include "asn1_locl.h"
+
+/* Generalised MIME like utilities for streaming ASN1. Although many
+ * have a PKCS7/CMS like flavour others are more general purpose.
+ */
+
+/* MIME format structures
+ * Note that all are translated to lower case apart from
+ * parameter values. Quotes are stripped off
+ */
+
+typedef struct {
+char *param_name; /* Param name e.g. "micalg" */
+char *param_value; /* Param value e.g. "sha1" */
+} MIME_PARAM;
+
+DECLARE_STACK_OF(MIME_PARAM)
+IMPLEMENT_STACK_OF(MIME_PARAM)
+
+typedef struct {
+char *name; /* Name of line e.g. "content-type" */
+char *value; /* Value of line e.g. "text/plain" */
+STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */
+} MIME_HEADER;
+
+DECLARE_STACK_OF(MIME_HEADER)
+IMPLEMENT_STACK_OF(MIME_HEADER)
+
+static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+ const ASN1_ITEM *it);
+static char * strip_ends(char *name);
+static char * strip_start(char *name);
+static char * strip_end(char *name);
+static MIME_HEADER *mime_hdr_new(char *name, char *value);
+static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value);
+static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
+static int mime_hdr_cmp(const MIME_HEADER * const *a,
+ const MIME_HEADER * const *b);
+static int mime_param_cmp(const MIME_PARAM * const *a,
+ const MIME_PARAM * const *b);
+static void mime_param_free(MIME_PARAM *param);
+static int mime_bound_check(char *line, int linelen, char *bound, int blen);
+static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
+static int strip_eol(char *linebuf, int *plen);
+static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
+static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
+static void mime_hdr_free(MIME_HEADER *hdr);
+
+#define MAX_SMLEN 1024
+#define mime_debug(x) /* x */
+
+/* Output an ASN1 structure in BER format streaming if necessary */
+
+int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const ASN1_ITEM *it)
+ {
+ /* If streaming create stream BIO and copy all content through it */
+ if (flags & SMIME_STREAM)
+ {
+ BIO *bio, *tbio;
+ bio = BIO_new_NDEF(out, val, it);
+ if (!bio)
+ {
+ ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ SMIME_crlf_copy(in, bio, flags);
+ (void)BIO_flush(bio);
+ /* Free up successive BIOs until we hit the old output BIO */
+ do
+ {
+ tbio = BIO_pop(bio);
+ BIO_free(bio);
+ bio = tbio;
+ } while (bio != out);
+ }
+ /* else just write out ASN1 structure which will have all content
+ * stored internally
+ */
+ else
+ ASN1_item_i2d_bio(it, out, val);
+ return 1;
+ }
+
+/* Base 64 read and write of ASN1 structure */
+
+static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const ASN1_ITEM *it)
+ {
+ BIO *b64;
+ int r;
+ b64 = BIO_new(BIO_f_base64());
+ if(!b64)
+ {
+ ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /* prepend the b64 BIO so all data is base64 encoded.
+ */
+ out = BIO_push(b64, out);
+ r = i2d_ASN1_bio_stream(out, val, in, flags, it);
+ (void)BIO_flush(out);
+ BIO_pop(out);
+ BIO_free(b64);
+ return r;
+ }
+
+/* Streaming ASN1 PEM write */
+
+int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+ const char *hdr,
+ const ASN1_ITEM *it)
+ {
+ int r;
+ BIO_printf(out, "-----BEGIN %s-----\n", hdr);
+ r = B64_write_ASN1(out, val, in, flags, it);
+ BIO_printf(out, "-----END %s-----\n", hdr);
+ return r;
+ }
+
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
+{
+ BIO *b64;
+ ASN1_VALUE *val;
+ if(!(b64 = BIO_new(BIO_f_base64()))) {
+ ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ bio = BIO_push(b64, bio);
+ val = ASN1_item_d2i_bio(it, bio, NULL);
+ if(!val)
+ ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR);
+ (void)BIO_flush(bio);
+ bio = BIO_pop(bio);
+ BIO_free(b64);
+ return val;
+}
+
+/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
+
+static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
+ {
+ const EVP_MD *md;
+ int i, have_unknown = 0, write_comma, ret = 0, md_nid;
+ have_unknown = 0;
+ write_comma = 0;
+ for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++)
+ {
+ if (write_comma)
+ BIO_write(out, ",", 1);
+ write_comma = 1;
+ md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
+ md = EVP_get_digestbynid(md_nid);
+ if (md && md->md_ctrl)
+ {
+ int rv;
+ char *micstr;
+ rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
+ if (rv > 0)
+ {
+ BIO_puts(out, micstr);
+ OPENSSL_free(micstr);
+ continue;
+ }
+ if (rv != -2)
+ goto err;
+ }
+ switch(md_nid)
+ {
+ case NID_sha1:
+ BIO_puts(out, "sha1");
+ break;
+
+ case NID_md5:
+ BIO_puts(out, "md5");
+ break;
+
+ case NID_sha256:
+ BIO_puts(out, "sha-256");
+ break;
+
+ case NID_sha384:
+ BIO_puts(out, "sha-384");
+ break;
+
+ case NID_sha512:
+ BIO_puts(out, "sha-512");
+ break;
+
+ case NID_id_GostR3411_94:
+ BIO_puts(out, "gostr3411-94");
+ goto err;
+ break;
+
+ default:
+ if (have_unknown)
+ write_comma = 0;
+ else
+ {
+ BIO_puts(out, "unknown");
+ have_unknown = 1;
+ }
+ break;
+
+ }
+ }
+
+ ret = 1;
+ err:
+
+ return ret;
+
+ }
+
+/* SMIME sender */
+
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+ int ctype_nid,
+ STACK_OF(X509_ALGOR) *mdalgs,
+ const ASN1_ITEM *it)
+{
+ char bound[33], c;
+ int i;
+ const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
+ const char *msg_type=NULL;
+ if (flags & SMIME_OLDMIME)
+ mime_prefix = "application/x-pkcs7-";
+ else
+ mime_prefix = "application/pkcs7-";
+
+ if (flags & SMIME_CRLFEOL)
+ mime_eol = "\r\n";
+ else
+ mime_eol = "\n";
+ if((flags & SMIME_DETACHED) && data) {
+ /* We want multipart/signed */
+ /* Generate a random boundary */
+ RAND_pseudo_bytes((unsigned char *)bound, 32);
+ for(i = 0; i < 32; i++) {
+ c = bound[i] & 0xf;
+ if(c < 10) c += '0';
+ else c += 'A' - 10;
+ bound[i] = c;
+ }
+ bound[32] = 0;
+ BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
+ BIO_printf(bio, "Content-Type: multipart/signed;");
+ BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
+ BIO_puts(bio, " micalg=\"");
+ asn1_write_micalg(bio, mdalgs);
+ BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
+ bound, mime_eol, mime_eol);
+ BIO_printf(bio, "This is an S/MIME signed message%s%s",
+ mime_eol, mime_eol);
+ /* Now write out the first part */
+ BIO_printf(bio, "------%s%s", bound, mime_eol);
+ if (!asn1_output_data(bio, data, val, flags, it))
+ return 0;
+ BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
+
+ /* Headers for signature */
+
+ BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
+ BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
+ BIO_printf(bio, "Content-Transfer-Encoding: base64%s",
+ mime_eol);
+ BIO_printf(bio, "Content-Disposition: attachment;");
+ BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
+ mime_eol, mime_eol);
+ B64_write_ASN1(bio, val, NULL, 0, it);
+ BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound,
+ mime_eol, mime_eol);
+ return 1;
+ }
+
+ /* Determine smime-type header */
+
+ if (ctype_nid == NID_pkcs7_enveloped)
+ msg_type = "enveloped-data";
+ else if (ctype_nid == NID_pkcs7_signed)
+ {
+ if (sk_X509_ALGOR_num(mdalgs) >= 0)
+ msg_type = "signed-data";
+ else
+ msg_type = "certs-only";
+ }
+ else if (ctype_nid == NID_id_smime_ct_compressedData)
+ {
+ msg_type = "compressed-data";
+ cname = "smime.p7z";
+ }
+ /* MIME headers */
+ BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
+ BIO_printf(bio, "Content-Disposition: attachment;");
+ BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
+ BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
+ if (msg_type)
+ BIO_printf(bio, " smime-type=%s;", msg_type);
+ BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
+ BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
+ mime_eol, mime_eol);
+ if (!B64_write_ASN1(bio, val, data, flags, it))
+ return 0;
+ BIO_printf(bio, "%s", mime_eol);
+ return 1;
+}
+
+/* Handle output of ASN1 data */
+
+
+static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+ const ASN1_ITEM *it)
+ {
+ BIO *tmpbio;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_STREAM_ARG sarg;
+
+ if (!(flags & SMIME_DETACHED))
+ {
+ SMIME_crlf_copy(data, out, flags);
+ return 1;
+ }
+
+ if (!aux || !aux->asn1_cb)
+ {
+ ASN1err(ASN1_F_ASN1_OUTPUT_DATA,
+ ASN1_R_STREAMING_NOT_SUPPORTED);
+ return 0;
+ }
+
+ sarg.out = out;
+ sarg.ndef_bio = NULL;
+ sarg.boundary = NULL;
+
+ /* Let ASN1 code prepend any needed BIOs */
+
+ if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
+ return 0;
+
+ /* Copy data across, passing through filter BIOs for processing */
+ SMIME_crlf_copy(data, sarg.ndef_bio, flags);
+
+ /* Finalize structure */
+ if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
+ return 0;
+
+ /* Now remove any digests prepended to the BIO */
+
+ while (sarg.ndef_bio != out)
+ {
+ tmpbio = BIO_pop(sarg.ndef_bio);
+ BIO_free(sarg.ndef_bio);
+ sarg.ndef_bio = tmpbio;
+ }
+
+ return 1;
+
+ }
+
+/* SMIME reader: handle multipart/signed and opaque signing.
+ * in multipart case the content is placed in a memory BIO
+ * pointed to by "bcont". In opaque this is set to NULL
+ */
+
+ASN1_VALUE *SMIME_read_asn1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+{
+ BIO *asnin;
+ STACK_OF(MIME_HEADER) *headers = NULL;
+ STACK_OF(BIO) *parts = NULL;
+ MIME_HEADER *hdr;
+ MIME_PARAM *prm;
+ ASN1_VALUE *val;
+ int ret;
+
+ if(bcont) *bcont = NULL;
+
+ if (!(headers = mime_parse_hdr(bio))) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR);
+ return NULL;
+ }
+
+ if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
+ return NULL;
+ }
+
+ /* Handle multipart/signed */
+
+ if(!strcmp(hdr->value, "multipart/signed")) {
+ /* Split into two parts */
+ prm = mime_param_find(hdr, "boundary");
+ if(!prm || !prm->param_value) {
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
+ return NULL;
+ }
+ ret = multi_split(bio, prm->param_value, &parts);
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ if(!ret || (sk_BIO_num(parts) != 2) ) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
+ sk_BIO_pop_free(parts, BIO_vfree);
+ return NULL;
+ }
+
+ /* Parse the signature piece */
+ asnin = sk_BIO_value(parts, 1);
+
+ if (!(headers = mime_parse_hdr(asnin))) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR);
+ sk_BIO_pop_free(parts, BIO_vfree);
+ return NULL;
+ }
+
+ /* Get content type */
+
+ if(!(hdr = mime_hdr_find(headers, "content-type")) ||
+ !hdr->value) {
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
+ return NULL;
+ }
+
+ if(strcmp(hdr->value, "application/x-pkcs7-signature") &&
+ strcmp(hdr->value, "application/pkcs7-signature")) {
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE);
+ ERR_add_error_data(2, "type: ", hdr->value);
+ sk_BIO_pop_free(parts, BIO_vfree);
+ return NULL;
+ }
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ /* Read in ASN1 */
+ if(!(val = b64_read_asn1(asnin, it))) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR);
+ sk_BIO_pop_free(parts, BIO_vfree);
+ return NULL;
+ }
+
+ if(bcont) {
+ *bcont = sk_BIO_value(parts, 0);
+ BIO_free(asnin);
+ sk_BIO_free(parts);
+ } else sk_BIO_pop_free(parts, BIO_vfree);
+ return val;
+ }
+
+ /* OK, if not multipart/signed try opaque signature */
+
+ if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
+ strcmp (hdr->value, "application/pkcs7-mime")) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE);
+ ERR_add_error_data(2, "type: ", hdr->value);
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ return NULL;
+ }
+
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+
+ if(!(val = b64_read_asn1(bio, it))) {
+ ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
+ return NULL;
+ }
+ return val;
+
+}
+
+/* Copy text from one BIO to another making the output CRLF at EOL */
+int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
+{
+ BIO *bf;
+ char eol;
+ int len;
+ char linebuf[MAX_SMLEN];
+ /* Buffer output so we don't write one line at a time. This is
+ * useful when streaming as we don't end up with one OCTET STRING
+ * per line.
+ */
+ bf = BIO_new(BIO_f_buffer());
+ if (!bf)
+ return 0;
+ out = BIO_push(bf, out);
+ if(flags & SMIME_BINARY)
+ {
+ while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
+ BIO_write(out, linebuf, len);
+ }
+ else
+ {
+ if(flags & SMIME_TEXT)
+ BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
+ while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
+ {
+ eol = strip_eol(linebuf, &len);
+ if (len)
+ BIO_write(out, linebuf, len);
+ if(eol) BIO_write(out, "\r\n", 2);
+ }
+ }
+ (void)BIO_flush(out);
+ BIO_pop(out);
+ BIO_free(bf);
+ return 1;
+}
+
+/* Strip off headers if they are text/plain */
+int SMIME_text(BIO *in, BIO *out)
+{
+ char iobuf[4096];
+ int len;
+ STACK_OF(MIME_HEADER) *headers;
+ MIME_HEADER *hdr;
+
+ if (!(headers = mime_parse_hdr(in))) {
+ ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR);
+ return 0;
+ }
+ if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
+ ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE);
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ return 0;
+ }
+ if (strcmp (hdr->value, "text/plain")) {
+ ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE);
+ ERR_add_error_data(2, "type: ", hdr->value);
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ return 0;
+ }
+ sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+ while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
+ BIO_write(out, iobuf, len);
+ return 1;
+}
+
+/* Split a multipart/XXX message body into component parts: result is
+ * canonical parts in a STACK of bios
+ */
+
+static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
+{
+ char linebuf[MAX_SMLEN];
+ int len, blen;
+ int eol = 0, next_eol = 0;
+ BIO *bpart = NULL;
+ STACK_OF(BIO) *parts;
+ char state, part, first;
+
+ blen = strlen(bound);
+ part = 0;
+ state = 0;
+ first = 1;
+ parts = sk_BIO_new_null();
+ *ret = parts;
+ while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+ state = mime_bound_check(linebuf, len, bound, blen);
+ if(state == 1) {
+ first = 1;
+ part++;
+ } else if(state == 2) {
+ sk_BIO_push(parts, bpart);
+ return 1;
+ } else if(part) {
+ /* Strip CR+LF from linebuf */
+ next_eol = strip_eol(linebuf, &len);
+ if(first) {
+ first = 0;
+ if(bpart) sk_BIO_push(parts, bpart);
+ bpart = BIO_new(BIO_s_mem());
+ BIO_set_mem_eof_return(bpart, 0);
+ } else if (eol)
+ BIO_write(bpart, "\r\n", 2);
+ eol = next_eol;
+ if (len)
+ BIO_write(bpart, linebuf, len);
+ }
+ }
+ return 0;
+}
+
+/* This is the big one: parse MIME header lines up to message body */
+
+#define MIME_INVALID 0
+#define MIME_START 1
+#define MIME_TYPE 2
+#define MIME_NAME 3
+#define MIME_VALUE 4
+#define MIME_QUOTE 5
+#define MIME_COMMENT 6
+
+
+static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
+{
+ char *p, *q, c;
+ char *ntmp;
+ char linebuf[MAX_SMLEN];
+ MIME_HEADER *mhdr = NULL;
+ STACK_OF(MIME_HEADER) *headers;
+ int len, state, save_state = 0;
+
+ headers = sk_MIME_HEADER_new(mime_hdr_cmp);
+ while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+ /* If whitespace at line start then continuation line */
+ if(mhdr && isspace((unsigned char)linebuf[0])) state = MIME_NAME;
+ else state = MIME_START;
+ ntmp = NULL;
+ /* Go through all characters */
+ for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
+
+ /* State machine to handle MIME headers
+ * if this looks horrible that's because it *is*
+ */
+
+ switch(state) {
+ case MIME_START:
+ if(c == ':') {
+ state = MIME_TYPE;
+ *p = 0;
+ ntmp = strip_ends(q);
+ q = p + 1;
+ }
+ break;
+
+ case MIME_TYPE:
+ if(c == ';') {
+ mime_debug("Found End Value\n");
+ *p = 0;
+ mhdr = mime_hdr_new(ntmp, strip_ends(q));
+ sk_MIME_HEADER_push(headers, mhdr);
+ ntmp = NULL;
+ q = p + 1;
+ state = MIME_NAME;
+ } else if(c == '(') {
+ save_state = state;
+ state = MIME_COMMENT;
+ }
+ break;
+
+ case MIME_COMMENT:
+ if(c == ')') {
+ state = save_state;
+ }
+ break;
+
+ case MIME_NAME:
+ if(c == '=') {
+ state = MIME_VALUE;
+ *p = 0;
+ ntmp = strip_ends(q);
+ q = p + 1;
+ }
+ break ;
+
+ case MIME_VALUE:
+ if(c == ';') {
+ state = MIME_NAME;
+ *p = 0;
+ mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
+ ntmp = NULL;
+ q = p + 1;
+ } else if (c == '"') {
+ mime_debug("Found Quote\n");
+ state = MIME_QUOTE;
+ } else if(c == '(') {
+ save_state = state;
+ state = MIME_COMMENT;
+ }
+ break;
+
+ case MIME_QUOTE:
+ if(c == '"') {
+ mime_debug("Found Match Quote\n");
+ state = MIME_VALUE;
+ }
+ break;
+ }
+ }
+
+ if(state == MIME_TYPE) {
+ mhdr = mime_hdr_new(ntmp, strip_ends(q));
+ sk_MIME_HEADER_push(headers, mhdr);
+ } else if(state == MIME_VALUE)
+ mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
+ if(p == linebuf) break; /* Blank line means end of headers */
+}
+
+return headers;
+
+}
+
+static char *strip_ends(char *name)
+{
+ return strip_end(strip_start(name));
+}
+
+/* Strip a parameter of whitespace from start of param */
+static char *strip_start(char *name)
+{
+ char *p, c;
+ /* Look for first non white space or quote */
+ for(p = name; (c = *p) ;p++) {
+ if(c == '"') {
+ /* Next char is start of string if non null */
+ if(p[1]) return p + 1;
+ /* Else null string */
+ return NULL;
+ }
+ if(!isspace((unsigned char)c)) return p;
+ }
+ return NULL;
+}
+
+/* As above but strip from end of string : maybe should handle brackets? */
+static char *strip_end(char *name)
+{
+ char *p, c;
+ if(!name) return NULL;
+ /* Look for first non white space or quote */
+ for(p = name + strlen(name) - 1; p >= name ;p--) {
+ c = *p;
+ if(c == '"') {
+ if(p - 1 == name) return NULL;
+ *p = 0;
+ return name;
+ }
+ if(isspace((unsigned char)c)) *p = 0;
+ else return name;
+ }
+ return NULL;
+}
+
+static MIME_HEADER *mime_hdr_new(char *name, char *value)
+{
+ MIME_HEADER *mhdr;
+ char *tmpname, *tmpval, *p;
+ int c;
+ if(name) {
+ if(!(tmpname = BUF_strdup(name))) return NULL;
+ for(p = tmpname ; *p; p++) {
+ c = *p;
+ if(isupper(c)) {
+ c = tolower(c);
+ *p = c;
+ }
+ }
+ } else tmpname = NULL;
+ if(value) {
+ if(!(tmpval = BUF_strdup(value))) return NULL;
+ for(p = tmpval ; *p; p++) {
+ c = *p;
+ if(isupper(c)) {
+ c = tolower(c);
+ *p = c;
+ }
+ }
+ } else tmpval = NULL;
+ mhdr = (MIME_HEADER *) OPENSSL_malloc(sizeof(MIME_HEADER));
+ if(!mhdr) return NULL;
+ mhdr->name = tmpname;
+ mhdr->value = tmpval;
+ if(!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) return NULL;
+ return mhdr;
+}
+
+static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
+{
+ char *tmpname, *tmpval, *p;
+ int c;
+ MIME_PARAM *mparam;
+ if(name) {
+ tmpname = BUF_strdup(name);
+ if(!tmpname) return 0;
+ for(p = tmpname ; *p; p++) {
+ c = *p;
+ if(isupper(c)) {
+ c = tolower(c);
+ *p = c;
+ }
+ }
+ } else tmpname = NULL;
+ if(value) {
+ tmpval = BUF_strdup(value);
+ if(!tmpval) return 0;
+ } else tmpval = NULL;
+ /* Parameter values are case sensitive so leave as is */
+ mparam = (MIME_PARAM *) OPENSSL_malloc(sizeof(MIME_PARAM));
+ if(!mparam) return 0;
+ mparam->param_name = tmpname;
+ mparam->param_value = tmpval;
+ sk_MIME_PARAM_push(mhdr->params, mparam);
+ return 1;
+}
+
+static int mime_hdr_cmp(const MIME_HEADER * const *a,
+ const MIME_HEADER * const *b)
+{
+ return(strcmp((*a)->name, (*b)->name));
+}
+
+static int mime_param_cmp(const MIME_PARAM * const *a,
+ const MIME_PARAM * const *b)
+{
+ return(strcmp((*a)->param_name, (*b)->param_name));
+}
+
+/* Find a header with a given name (if possible) */
+
+static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name)
+{
+ MIME_HEADER htmp;
+ int idx;
+ htmp.name = name;
+ idx = sk_MIME_HEADER_find(hdrs, &htmp);
+ if(idx < 0) return NULL;
+ return sk_MIME_HEADER_value(hdrs, idx);
+}
+
+static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name)
+{
+ MIME_PARAM param;
+ int idx;
+ param.param_name = name;
+ idx = sk_MIME_PARAM_find(hdr->params, &param);
+ if(idx < 0) return NULL;
+ return sk_MIME_PARAM_value(hdr->params, idx);
+}
+
+static void mime_hdr_free(MIME_HEADER *hdr)
+{
+ if(hdr->name) OPENSSL_free(hdr->name);
+ if(hdr->value) OPENSSL_free(hdr->value);
+ if(hdr->params) sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
+ OPENSSL_free(hdr);
+}
+
+static void mime_param_free(MIME_PARAM *param)
+{
+ if(param->param_name) OPENSSL_free(param->param_name);
+ if(param->param_value) OPENSSL_free(param->param_value);
+ OPENSSL_free(param);
+}
+
+/* Check for a multipart boundary. Returns:
+ * 0 : no boundary
+ * 1 : part boundary
+ * 2 : final boundary
+ */
+static int mime_bound_check(char *line, int linelen, char *bound, int blen)
+{
+ if(linelen == -1) linelen = strlen(line);
+ if(blen == -1) blen = strlen(bound);
+ /* Quickly eliminate if line length too short */
+ if(blen + 2 > linelen) return 0;
+ /* Check for part boundary */
+ if(!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) {
+ if(!strncmp(line + blen + 2, "--", 2)) return 2;
+ else return 1;
+ }
+ return 0;
+}
+
+static int strip_eol(char *linebuf, int *plen)
+ {
+ int len = *plen;
+ char *p, c;
+ int is_eol = 0;
+ p = linebuf + len - 1;
+ for (p = linebuf + len - 1; len > 0; len--, p--)
+ {
+ c = *p;
+ if (c == '\n')
+ is_eol = 1;
+ else if (c != '\r')
+ break;
+ }
+ *plen = len;
+ return is_eol;
+ }
diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c
new file mode 100644
index 0000000000..96074802d3
--- /dev/null
+++ b/crypto/asn1/bio_ndef.c
@@ -0,0 +1,246 @@
+/* bio_ndef.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 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.
+ * ====================================================================
+ *
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+#ifndef OPENSSL_SYSNAME_NETWARE
+#include <memory.h>
+#endif
+#include <stdio.h>
+
+/* Experimental NDEF ASN1 BIO support routines */
+
+/* The usage is quite simple, initialize an ASN1 structure,
+ * get a BIO from it then any data written through the BIO
+ * will end up translated to approptiate format on the fly.
+ * The data is streamed out and does *not* need to be
+ * all held in memory at once.
+ *
+ * When the BIO is flushed the output is finalized and any
+ * signatures etc written out.
+ *
+ * The BIO is a 'proper' BIO and can handle non blocking I/O
+ * correctly.
+ *
+ * The usage is simple. The implementation is *not*...
+ */
+
+/* BIO support data stored in the ASN1 BIO ex_arg */
+
+typedef struct ndef_aux_st
+ {
+ /* ASN1 structure this BIO refers to */
+ ASN1_VALUE *val;
+ const ASN1_ITEM *it;
+ /* Top of the BIO chain */
+ BIO *ndef_bio;
+ /* Output BIO */
+ BIO *out;
+ /* Boundary where content is inserted */
+ unsigned char **boundary;
+ /* DER buffer start */
+ unsigned char *derbuf;
+ } NDEF_SUPPORT;
+
+static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+
+BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
+ {
+ NDEF_SUPPORT *ndef_aux = NULL;
+ BIO *asn_bio = NULL;
+ const ASN1_AUX *aux = it->funcs;
+ ASN1_STREAM_ARG sarg;
+
+ if (!aux && !aux->asn1_cb)
+ {
+ ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
+ return NULL;
+ }
+ ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
+ asn_bio = BIO_new(BIO_f_asn1());
+
+ /* ASN1 bio needs to be next to output BIO */
+
+ out = BIO_push(asn_bio, out);
+
+ if (!ndef_aux || !asn_bio || !out)
+ goto err;
+
+ BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
+ BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
+
+ /* Now let callback prepend any digest, cipher etc BIOs
+ * ASN1 structure needs.
+ */
+
+ sarg.out = out;
+ sarg.ndef_bio = NULL;
+ sarg.boundary = NULL;
+
+ if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
+ goto err;
+
+ ndef_aux->val = val;
+ ndef_aux->it = it;
+ ndef_aux->ndef_bio = sarg.ndef_bio;
+ ndef_aux->boundary = sarg.boundary;
+ ndef_aux->out = out;
+
+ BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
+
+ return sarg.ndef_bio;
+
+ err:
+ if (asn_bio)
+ BIO_free(asn_bio);
+ if (ndef_aux)
+ OPENSSL_free(ndef_aux);
+ return NULL;
+ }
+
+static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+ {
+ NDEF_SUPPORT *ndef_aux;
+ unsigned char *p;
+ int derlen;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+
+ if (!*ndef_aux->boundary)
+ return 0;
+
+ *plen = *ndef_aux->boundary - *pbuf;
+
+ return 1;
+ }
+
+static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+ {
+ NDEF_SUPPORT *ndef_aux;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ if (ndef_aux->derbuf)
+ OPENSSL_free(ndef_aux->derbuf);
+
+ ndef_aux->derbuf = NULL;
+ *pbuf = NULL;
+ *plen = 0;
+ return 1;
+ }
+
+static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+ {
+ NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
+ if (!ndef_prefix_free(b, pbuf, plen, parg))
+ return 0;
+ OPENSSL_free(*pndef_aux);
+ *pndef_aux = NULL;
+ return 1;
+ }
+
+static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+ {
+ NDEF_SUPPORT *ndef_aux;
+ unsigned char *p;
+ int derlen;
+ const ASN1_AUX *aux;
+ ASN1_STREAM_ARG sarg;
+
+ if (!parg)
+ return 0;
+
+ ndef_aux = *(NDEF_SUPPORT **)parg;
+
+ aux = ndef_aux->it->funcs;
+
+ /* Finalize structures */
+ sarg.ndef_bio = ndef_aux->ndef_bio;
+ sarg.out = ndef_aux->out;
+ sarg.boundary = ndef_aux->boundary;
+ if (aux->asn1_cb(ASN1_OP_STREAM_POST,
+ &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
+ return 0;
+
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+ p = OPENSSL_malloc(derlen);
+ ndef_aux->derbuf = p;
+ *pbuf = p;
+ derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+
+ if (!*ndef_aux->boundary)
+ return 0;
+ *pbuf = *ndef_aux->boundary;
+ *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
+
+ return 1;
+ }
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
index f3355e7a12..19820125e4 100644
--- a/crypto/asn1/p5_pbe.c
+++ b/crypto/asn1/p5_pbe.c
@@ -71,61 +71,78 @@ ASN1_SEQUENCE(PBEPARAM) = {
IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
-/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter, unsigned char *salt,
- int saltlen)
-{
+/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
+
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+ const unsigned char *salt, int saltlen)
+ {
PBEPARAM *pbe=NULL;
- ASN1_OBJECT *al;
- X509_ALGOR *algor;
- ASN1_TYPE *astype=NULL;
+ ASN1_STRING *pbe_str=NULL;
+ unsigned char *sstr;
- if (!(pbe = PBEPARAM_new ())) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
+ pbe = PBEPARAM_new();
+ if (!pbe)
+ {
+ ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
goto err;
- }
- if(iter <= 0) iter = PKCS5_DEFAULT_ITER;
- if (!ASN1_INTEGER_set(pbe->iter, iter)) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
+ }
+ if(iter <= 0)
+ iter = PKCS5_DEFAULT_ITER;
+ if (!ASN1_INTEGER_set(pbe->iter, iter))
+ {
+ ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
goto err;
- }
- if (!saltlen) saltlen = PKCS5_SALT_LEN;
- if (!(pbe->salt->data = OPENSSL_malloc (saltlen))) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
+ }
+ if (!saltlen)
+ saltlen = PKCS5_SALT_LEN;
+ if (!ASN1_STRING_set(pbe->salt, NULL, saltlen))
+ {
+ ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
goto err;
- }
- pbe->salt->length = saltlen;
- if (salt) memcpy (pbe->salt->data, salt, saltlen);
- else if (RAND_pseudo_bytes (pbe->salt->data, saltlen) < 0)
+ }
+ sstr = ASN1_STRING_data(pbe->salt);
+ if (salt)
+ memcpy(sstr, salt, saltlen);
+ else if (RAND_pseudo_bytes(sstr, saltlen) < 0)
goto err;
- if (!(astype = ASN1_TYPE_new())) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
+ if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
+ {
+ ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR,ERR_R_MALLOC_FAILURE);
goto err;
- }
+ }
- astype->type = V_ASN1_SEQUENCE;
- if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM),
- &astype->value.sequence)) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- PBEPARAM_free (pbe);
+ PBEPARAM_free(pbe);
pbe = NULL;
-
- al = OBJ_nid2obj(alg); /* never need to free al */
- if (!(algor = X509_ALGOR_new())) {
- ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ASN1_OBJECT_free(algor->algorithm);
- algor->algorithm = al;
- algor->parameter = astype;
- return (algor);
+ if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
+ return 1;
+
err:
- if (pbe != NULL) PBEPARAM_free(pbe);
- if (astype != NULL) ASN1_TYPE_free(astype);
+ if (pbe != NULL)
+ PBEPARAM_free(pbe);
+ if (pbe_str != NULL)
+ ASN1_STRING_free(pbe_str);
+ return 0;
+ }
+
+/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+ const unsigned char *salt, int saltlen)
+ {
+ X509_ALGOR *ret;
+ ret = X509_ALGOR_new();
+ if (!ret)
+ {
+ ASN1err(ASN1_F_PKCS5_PBE_SET,ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+ return ret;
+
+ X509_ALGOR_free(ret);
return NULL;
-}
+ }
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
index bd6a8d6ad5..33533aba86 100644
--- a/crypto/asn1/x_algor.c
+++ b/crypto/asn1/x_algor.c
@@ -66,7 +66,12 @@ ASN1_SEQUENCE(X509_ALGOR) = {
ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
} ASN1_SEQUENCE_END(X509_ALGOR)
+ASN1_ITEM_TEMPLATE(X509_ALGORS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
+
IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
IMPLEMENT_STACK_OF(X509_ALGOR)