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