Line data Source code
1 : /* bio_ndef.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 : * project.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : */
55 :
56 : #include <openssl/asn1.h>
57 : #include <openssl/asn1t.h>
58 : #include <openssl/bio.h>
59 : #include <openssl/err.h>
60 :
61 : #include <stdio.h>
62 :
63 : /* Experimental NDEF ASN1 BIO support routines */
64 :
65 : /*
66 : * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
67 : * then any data written through the BIO will end up translated to
68 : * approptiate format on the fly. The data is streamed out and does *not*
69 : * need to be all held in memory at once. When the BIO is flushed the output
70 : * is finalized and any signatures etc written out. The BIO is a 'proper'
71 : * BIO and can handle non blocking I/O correctly. The usage is simple. The
72 : * implementation is *not*...
73 : */
74 :
75 : /* BIO support data stored in the ASN1 BIO ex_arg */
76 :
77 : typedef struct ndef_aux_st {
78 : /* ASN1 structure this BIO refers to */
79 : ASN1_VALUE *val;
80 : const ASN1_ITEM *it;
81 : /* Top of the BIO chain */
82 : BIO *ndef_bio;
83 : /* Output BIO */
84 : BIO *out;
85 : /* Boundary where content is inserted */
86 : unsigned char **boundary;
87 : /* DER buffer start */
88 : unsigned char *derbuf;
89 : } NDEF_SUPPORT;
90 :
91 : static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
92 : static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
93 : void *parg);
94 : static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
95 : static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
96 : void *parg);
97 :
98 0 : BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
99 : {
100 : NDEF_SUPPORT *ndef_aux = NULL;
101 : BIO *asn_bio = NULL;
102 0 : const ASN1_AUX *aux = it->funcs;
103 : ASN1_STREAM_ARG sarg;
104 :
105 0 : if (!aux || !aux->asn1_cb) {
106 0 : ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
107 0 : return NULL;
108 : }
109 0 : ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
110 0 : asn_bio = BIO_new(BIO_f_asn1());
111 :
112 : /* ASN1 bio needs to be next to output BIO */
113 :
114 0 : out = BIO_push(asn_bio, out);
115 :
116 0 : if (!ndef_aux || !asn_bio || !out)
117 : goto err;
118 :
119 0 : BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
120 0 : BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
121 :
122 : /*
123 : * Now let callback prepend any digest, cipher etc BIOs ASN1 structure
124 : * needs.
125 : */
126 :
127 0 : sarg.out = out;
128 0 : sarg.ndef_bio = NULL;
129 0 : sarg.boundary = NULL;
130 :
131 0 : if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
132 : goto err;
133 :
134 0 : ndef_aux->val = val;
135 0 : ndef_aux->it = it;
136 0 : ndef_aux->ndef_bio = sarg.ndef_bio;
137 0 : ndef_aux->boundary = sarg.boundary;
138 0 : ndef_aux->out = out;
139 :
140 0 : BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
141 :
142 0 : return sarg.ndef_bio;
143 :
144 : err:
145 0 : if (asn_bio)
146 0 : BIO_free(asn_bio);
147 0 : if (ndef_aux)
148 0 : OPENSSL_free(ndef_aux);
149 : return NULL;
150 : }
151 :
152 0 : static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
153 : {
154 : NDEF_SUPPORT *ndef_aux;
155 : unsigned char *p;
156 : int derlen;
157 :
158 0 : if (!parg)
159 : return 0;
160 :
161 0 : ndef_aux = *(NDEF_SUPPORT **)parg;
162 :
163 0 : derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
164 0 : p = OPENSSL_malloc(derlen);
165 0 : if (!p)
166 : return 0;
167 :
168 0 : ndef_aux->derbuf = p;
169 0 : *pbuf = p;
170 0 : derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
171 :
172 0 : if (!*ndef_aux->boundary)
173 : return 0;
174 :
175 0 : *plen = *ndef_aux->boundary - *pbuf;
176 :
177 0 : return 1;
178 : }
179 :
180 0 : static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
181 : void *parg)
182 : {
183 : NDEF_SUPPORT *ndef_aux;
184 :
185 0 : if (!parg)
186 : return 0;
187 :
188 0 : ndef_aux = *(NDEF_SUPPORT **)parg;
189 :
190 0 : if (ndef_aux->derbuf)
191 0 : OPENSSL_free(ndef_aux->derbuf);
192 :
193 0 : ndef_aux->derbuf = NULL;
194 0 : *pbuf = NULL;
195 0 : *plen = 0;
196 0 : return 1;
197 : }
198 :
199 0 : static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
200 : void *parg)
201 : {
202 : NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
203 0 : if (!ndef_prefix_free(b, pbuf, plen, parg))
204 : return 0;
205 0 : OPENSSL_free(*pndef_aux);
206 0 : *pndef_aux = NULL;
207 0 : return 1;
208 : }
209 :
210 0 : static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
211 : {
212 : NDEF_SUPPORT *ndef_aux;
213 : unsigned char *p;
214 : int derlen;
215 : const ASN1_AUX *aux;
216 : ASN1_STREAM_ARG sarg;
217 :
218 0 : if (!parg)
219 : return 0;
220 :
221 0 : ndef_aux = *(NDEF_SUPPORT **)parg;
222 :
223 0 : aux = ndef_aux->it->funcs;
224 :
225 : /* Finalize structures */
226 0 : sarg.ndef_bio = ndef_aux->ndef_bio;
227 0 : sarg.out = ndef_aux->out;
228 0 : sarg.boundary = ndef_aux->boundary;
229 0 : if (aux->asn1_cb(ASN1_OP_STREAM_POST,
230 : &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
231 : return 0;
232 :
233 0 : derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
234 0 : p = OPENSSL_malloc(derlen);
235 0 : if (!p)
236 : return 0;
237 :
238 0 : ndef_aux->derbuf = p;
239 0 : *pbuf = p;
240 0 : derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
241 :
242 0 : if (!*ndef_aux->boundary)
243 : return 0;
244 0 : *pbuf = *ndef_aux->boundary;
245 0 : *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
246 :
247 0 : return 1;
248 : }
|