Home | History | Annotate | Download | only in asn1
      1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      2  * All rights reserved.
      3  *
      4  * This package is an SSL implementation written
      5  * by Eric Young (eay (at) cryptsoft.com).
      6  * The implementation was written so as to conform with Netscapes SSL.
      7  *
      8  * This library is free for commercial and non-commercial use as long as
      9  * the following conditions are aheared to.  The following conditions
     10  * apply to all code found in this distribution, be it the RC4, RSA,
     11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     12  * included with this distribution is covered by the same copyright terms
     13  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     14  *
     15  * Copyright remains Eric Young's, and as such any Copyright notices in
     16  * the code are not to be removed.
     17  * If this package is used in a product, Eric Young should be given attribution
     18  * as the author of the parts of the library used.
     19  * This can be in the form of a textual message at program startup or
     20  * in documentation (online or textual) provided with the package.
     21  *
     22  * Redistribution and use in source and binary forms, with or without
     23  * modification, are permitted provided that the following conditions
     24  * are met:
     25  * 1. Redistributions of source code must retain the copyright
     26  *    notice, this list of conditions and the following disclaimer.
     27  * 2. Redistributions in binary form must reproduce the above copyright
     28  *    notice, this list of conditions and the following disclaimer in the
     29  *    documentation and/or other materials provided with the distribution.
     30  * 3. All advertising materials mentioning features or use of this software
     31  *    must display the following acknowledgement:
     32  *    "This product includes cryptographic software written by
     33  *     Eric Young (eay (at) cryptsoft.com)"
     34  *    The word 'cryptographic' can be left out if the rouines from the library
     35  *    being used are not cryptographic related :-).
     36  * 4. If you include any Windows specific code (or a derivative thereof) from
     37  *    the apps directory (application code) you must include an acknowledgement:
     38  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     50  * SUCH DAMAGE.
     51  *
     52  * The licence and distribution terms for any publically available version or
     53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     54  * copied and put under another distribution licence
     55  * [including the GNU Public Licence.] */
     56 
     57 #include <openssl/asn1.h>
     58 
     59 #include <assert.h>
     60 
     61 #include <openssl/asn1t.h>
     62 #include <openssl/bio.h>
     63 #include <openssl/err.h>
     64 #include <openssl/mem.h>
     65 
     66 
     67 /* Experimental NDEF ASN1 BIO support routines */
     68 
     69 /* The usage is quite simple, initialize an ASN1 structure,
     70  * get a BIO from it then any data written through the BIO
     71  * will end up translated to approptiate format on the fly.
     72  * The data is streamed out and does *not* need to be
     73  * all held in memory at once.
     74  *
     75  * When the BIO is flushed the output is finalized and any
     76  * signatures etc written out.
     77  *
     78  * The BIO is a 'proper' BIO and can handle non blocking I/O
     79  * correctly.
     80  *
     81  * The usage is simple. The implementation is *not*...
     82  */
     83 
     84 /* BIO support data stored in the ASN1 BIO ex_arg */
     85 
     86 typedef struct ndef_aux_st
     87 	{
     88 	/* ASN1 structure this BIO refers to */
     89 	ASN1_VALUE *val;
     90 	const ASN1_ITEM *it;
     91 	/* Top of the BIO chain */
     92 	BIO *ndef_bio;
     93 	/* Output BIO */
     94 	BIO *out;
     95 	/* Boundary where content is inserted */
     96 	unsigned char **boundary;
     97 	/* DER buffer start */
     98 	unsigned char *derbuf;
     99 	} NDEF_SUPPORT;
    100 
    101 static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
    102 static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
    103 static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
    104 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
    105 
    106 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
    107 	{
    108 	NDEF_SUPPORT *ndef_aux = NULL;
    109 	BIO *asn_bio = NULL;
    110 	const ASN1_AUX *aux = it->funcs;
    111 	ASN1_STREAM_ARG sarg;
    112 
    113 	if (!aux || !aux->asn1_cb)
    114 		{
    115 		OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
    116 		return NULL;
    117 		}
    118 	ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
    119 	asn_bio = BIO_new(BIO_f_asn1());
    120 
    121 	/* ASN1 bio needs to be next to output BIO */
    122 
    123 	out = BIO_push(asn_bio, out);
    124 
    125 	if (!ndef_aux || !asn_bio || !out)
    126 		goto err;
    127 
    128 	BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
    129 	BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
    130 
    131 	/* Now let callback prepend any digest, cipher etc BIOs
    132 	 * ASN1 structure needs.
    133 	 */
    134 
    135 	sarg.out = out;
    136 	sarg.ndef_bio = NULL;
    137 	sarg.boundary = NULL;
    138 
    139 	if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
    140 		goto err;
    141 
    142 	ndef_aux->val = val;
    143 	ndef_aux->it = it;
    144 	ndef_aux->ndef_bio = sarg.ndef_bio;
    145 	ndef_aux->boundary = sarg.boundary;
    146 	ndef_aux->out = out;
    147 
    148 	BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
    149 
    150 	return sarg.ndef_bio;
    151 
    152 	err:
    153 	if (asn_bio)
    154 		BIO_free(asn_bio);
    155 	if (ndef_aux)
    156 		OPENSSL_free(ndef_aux);
    157 	return NULL;
    158 	}
    159 
    160 static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
    161 	{
    162 	NDEF_SUPPORT *ndef_aux;
    163 	unsigned char *p;
    164 	int derlen;
    165 
    166 	if (!parg)
    167 		return 0;
    168 
    169 	ndef_aux = *(NDEF_SUPPORT **)parg;
    170 
    171 	derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
    172 	p = OPENSSL_malloc(derlen);
    173 	if (p == NULL)
    174 		return 0;
    175 
    176 	ndef_aux->derbuf = p;
    177 	*pbuf = p;
    178 	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
    179 
    180 	if (!*ndef_aux->boundary)
    181 		return 0;
    182 
    183 	*plen = *ndef_aux->boundary - *pbuf;
    184 
    185 	return 1;
    186 	}
    187 
    188 static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
    189 	{
    190 	NDEF_SUPPORT *ndef_aux;
    191 
    192 	if (!parg)
    193 		return 0;
    194 
    195 	ndef_aux = *(NDEF_SUPPORT **)parg;
    196 
    197 	if (ndef_aux->derbuf)
    198 		OPENSSL_free(ndef_aux->derbuf);
    199 
    200 	ndef_aux->derbuf = NULL;
    201 	*pbuf = NULL;
    202 	*plen = 0;
    203 	return 1;
    204 	}
    205 
    206 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
    207 	{
    208 	NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
    209 	if (!ndef_prefix_free(b, pbuf, plen, parg))
    210 		return 0;
    211 	OPENSSL_free(*pndef_aux);
    212 	*pndef_aux = NULL;
    213 	return 1;
    214 	}
    215 
    216 static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
    217 	{
    218 	NDEF_SUPPORT *ndef_aux;
    219 	unsigned char *p;
    220 	int derlen;
    221 	const ASN1_AUX *aux;
    222 	ASN1_STREAM_ARG sarg;
    223 
    224 	if (!parg)
    225 		return 0;
    226 
    227 	ndef_aux = *(NDEF_SUPPORT **)parg;
    228 
    229 	aux = ndef_aux->it->funcs;
    230 
    231 	/* Finalize structures */
    232 	sarg.ndef_bio = ndef_aux->ndef_bio;
    233 	sarg.out = ndef_aux->out;
    234 	sarg.boundary = ndef_aux->boundary;
    235 	if (aux->asn1_cb(ASN1_OP_STREAM_POST,
    236 				&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
    237 		return 0;
    238 
    239 	derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
    240 	p = OPENSSL_malloc(derlen);
    241 	if (p == NULL)
    242 		return 0;
    243 
    244 	ndef_aux->derbuf = p;
    245 	*pbuf = p;
    246 	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
    247 
    248 	if (!*ndef_aux->boundary)
    249 		return 0;
    250 	*pbuf = *ndef_aux->boundary;
    251 	*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
    252 
    253 	return 1;
    254 	}
    255