1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@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@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@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@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
86typedef 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
101static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
102static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
103static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
104static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
105
106BIO *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, BIO_new_NDEF, 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
160static 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	ndef_aux->derbuf = p;
174	*pbuf = p;
175	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
176
177	if (!*ndef_aux->boundary)
178		return 0;
179
180	*plen = *ndef_aux->boundary - *pbuf;
181
182	return 1;
183	}
184
185static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
186	{
187	NDEF_SUPPORT *ndef_aux;
188
189	if (!parg)
190		return 0;
191
192	ndef_aux = *(NDEF_SUPPORT **)parg;
193
194	if (ndef_aux->derbuf)
195		OPENSSL_free(ndef_aux->derbuf);
196
197	ndef_aux->derbuf = NULL;
198	*pbuf = NULL;
199	*plen = 0;
200	return 1;
201	}
202
203static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
204	{
205	NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
206	if (!ndef_prefix_free(b, pbuf, plen, parg))
207		return 0;
208	OPENSSL_free(*pndef_aux);
209	*pndef_aux = NULL;
210	return 1;
211	}
212
213static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
214	{
215	NDEF_SUPPORT *ndef_aux;
216	unsigned char *p;
217	int derlen;
218	const ASN1_AUX *aux;
219	ASN1_STREAM_ARG sarg;
220
221	if (!parg)
222		return 0;
223
224	ndef_aux = *(NDEF_SUPPORT **)parg;
225
226	aux = ndef_aux->it->funcs;
227
228	/* Finalize structures */
229	sarg.ndef_bio = ndef_aux->ndef_bio;
230	sarg.out = ndef_aux->out;
231	sarg.boundary = ndef_aux->boundary;
232	if (aux->asn1_cb(ASN1_OP_STREAM_POST,
233				&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
234		return 0;
235
236	derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
237	p = OPENSSL_malloc(derlen);
238	ndef_aux->derbuf = p;
239	*pbuf = p;
240	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
241
242	if (!*ndef_aux->boundary)
243		return 0;
244	*pbuf = *ndef_aux->boundary;
245	*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
246
247	return 1;
248	}
249