bio_ndef.c revision 306195
1214501Srpaulo/* bio_ndef.c */ 2214501Srpaulo/* 3214501Srpaulo * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4214501Srpaulo * project. 5252726Srpaulo */ 6252726Srpaulo/* ==================================================================== 7214501Srpaulo * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8214501Srpaulo * 9214501Srpaulo * Redistribution and use in source and binary forms, with or without 10214501Srpaulo * modification, are permitted provided that the following conditions 11214501Srpaulo * are met: 12214501Srpaulo * 13214501Srpaulo * 1. Redistributions of source code must retain the above copyright 14214501Srpaulo * notice, this list of conditions and the following disclaimer. 15214501Srpaulo * 16214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 17214501Srpaulo * notice, this list of conditions and the following disclaimer in 18214501Srpaulo * the documentation and/or other materials provided with the 19214501Srpaulo * distribution. 20214501Srpaulo * 21214501Srpaulo * 3. All advertising materials mentioning features or use of this 22252726Srpaulo * software must display the following acknowledgment: 23214501Srpaulo * "This product includes software developed by the OpenSSL Project 24252726Srpaulo * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25252726Srpaulo * 26252726Srpaulo * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27252726Srpaulo * endorse or promote products derived from this software without 28214501Srpaulo * prior written permission. For written permission, please contact 29214501Srpaulo * licensing@OpenSSL.org. 30214501Srpaulo * 31214501Srpaulo * 5. Products derived from this software may not be called "OpenSSL" 32214501Srpaulo * nor may "OpenSSL" appear in their names without prior written 33214501Srpaulo * permission of the OpenSSL Project. 34252726Srpaulo * 35252726Srpaulo * 6. Redistributions of any form whatsoever must retain the following 36214501Srpaulo * acknowledgment: 37252726Srpaulo * "This product includes software developed by the OpenSSL Project 38252726Srpaulo * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39252726Srpaulo * 40214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41214501Srpaulo * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43214501Srpaulo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44214501Srpaulo * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45214501Srpaulo * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46214501Srpaulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47214501Srpaulo * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49214501Srpaulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50214501Srpaulo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51214501Srpaulo * OF THE POSSIBILITY OF SUCH DAMAGE. 52214501Srpaulo * ==================================================================== 53252726Srpaulo * 54252726Srpaulo */ 55214501Srpaulo 56214501Srpaulo#include <openssl/asn1.h> 57214501Srpaulo#include <openssl/asn1t.h> 58214501Srpaulo#include <openssl/bio.h> 59214501Srpaulo#include <openssl/err.h> 60214501Srpaulo 61214501Srpaulo#include <stdio.h> 62214501Srpaulo 63214501Srpaulo/* Experimental NDEF ASN1 BIO support routines */ 64252726Srpaulo 65252726Srpaulo/* 66252726Srpaulo * The usage is quite simple, initialize an ASN1 structure, get a BIO from it 67214501Srpaulo * then any data written through the BIO will end up translated to 68214501Srpaulo * approptiate format on the fly. The data is streamed out and does *not* 69214501Srpaulo * need to be all held in memory at once. When the BIO is flushed the output 70214501Srpaulo * is finalized and any signatures etc written out. The BIO is a 'proper' 71214501Srpaulo * BIO and can handle non blocking I/O correctly. The usage is simple. The 72214501Srpaulo * implementation is *not*... 73 */ 74 75/* BIO support data stored in the ASN1 BIO ex_arg */ 76 77typedef 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 91static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 92static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 93 void *parg); 94static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 95static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 96 void *parg); 97 98BIO *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 const ASN1_AUX *aux = it->funcs; 103 ASN1_STREAM_ARG sarg; 104 105 if (!aux || !aux->asn1_cb) { 106 ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 107 return NULL; 108 } 109 ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT)); 110 asn_bio = BIO_new(BIO_f_asn1()); 111 112 /* ASN1 bio needs to be next to output BIO */ 113 114 out = BIO_push(asn_bio, out); 115 116 if (!ndef_aux || !asn_bio || !out) 117 goto err; 118 119 BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); 120 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 sarg.out = out; 128 sarg.ndef_bio = NULL; 129 sarg.boundary = NULL; 130 131 if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) 132 goto err; 133 134 ndef_aux->val = val; 135 ndef_aux->it = it; 136 ndef_aux->ndef_bio = sarg.ndef_bio; 137 ndef_aux->boundary = sarg.boundary; 138 ndef_aux->out = out; 139 ndef_aux->derbuf = NULL; 140 141 BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); 142 143 return sarg.ndef_bio; 144 145 err: 146 if (asn_bio) 147 BIO_free(asn_bio); 148 if (ndef_aux) 149 OPENSSL_free(ndef_aux); 150 return NULL; 151} 152 153static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 154{ 155 NDEF_SUPPORT *ndef_aux; 156 unsigned char *p; 157 int derlen; 158 159 if (!parg) 160 return 0; 161 162 ndef_aux = *(NDEF_SUPPORT **)parg; 163 164 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 165 p = OPENSSL_malloc(derlen); 166 if (!p) 167 return 0; 168 169 ndef_aux->derbuf = p; 170 *pbuf = p; 171 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 172 173 if (!*ndef_aux->boundary) 174 return 0; 175 176 *plen = *ndef_aux->boundary - *pbuf; 177 178 return 1; 179} 180 181static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 182 void *parg) 183{ 184 NDEF_SUPPORT *ndef_aux; 185 186 if (!parg) 187 return 0; 188 189 ndef_aux = *(NDEF_SUPPORT **)parg; 190 191 if (ndef_aux->derbuf) 192 OPENSSL_free(ndef_aux->derbuf); 193 194 ndef_aux->derbuf = NULL; 195 *pbuf = NULL; 196 *plen = 0; 197 return 1; 198} 199 200static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 201 void *parg) 202{ 203 NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; 204 if (!ndef_prefix_free(b, pbuf, plen, parg)) 205 return 0; 206 OPENSSL_free(*pndef_aux); 207 *pndef_aux = NULL; 208 return 1; 209} 210 211static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 212{ 213 NDEF_SUPPORT *ndef_aux; 214 unsigned char *p; 215 int derlen; 216 const ASN1_AUX *aux; 217 ASN1_STREAM_ARG sarg; 218 219 if (!parg) 220 return 0; 221 222 ndef_aux = *(NDEF_SUPPORT **)parg; 223 224 aux = ndef_aux->it->funcs; 225 226 /* Finalize structures */ 227 sarg.ndef_bio = ndef_aux->ndef_bio; 228 sarg.out = ndef_aux->out; 229 sarg.boundary = ndef_aux->boundary; 230 if (aux->asn1_cb(ASN1_OP_STREAM_POST, 231 &ndef_aux->val, ndef_aux->it, &sarg) <= 0) 232 return 0; 233 234 derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 235 p = OPENSSL_malloc(derlen); 236 if (!p) 237 return 0; 238 239 ndef_aux->derbuf = p; 240 *pbuf = p; 241 derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 242 243 if (!*ndef_aux->boundary) 244 return 0; 245 *pbuf = *ndef_aux->boundary; 246 *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); 247 248 return 1; 249} 250