1238384Sjkim/* bio_ndef.c */ 2296341Sdelphij/* 3296341Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4238384Sjkim * project. 5238384Sjkim */ 6238384Sjkim/* ==================================================================== 7238384Sjkim * Copyright (c) 2008 The OpenSSL Project. All rights reserved. 8238384Sjkim * 9238384Sjkim * Redistribution and use in source and binary forms, with or without 10238384Sjkim * modification, are permitted provided that the following conditions 11238384Sjkim * are met: 12238384Sjkim * 13238384Sjkim * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 15238384Sjkim * 16238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 17238384Sjkim * notice, this list of conditions and the following disclaimer in 18238384Sjkim * the documentation and/or other materials provided with the 19238384Sjkim * distribution. 20238384Sjkim * 21238384Sjkim * 3. All advertising materials mentioning features or use of this 22238384Sjkim * software must display the following acknowledgment: 23238384Sjkim * "This product includes software developed by the OpenSSL Project 24238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25238384Sjkim * 26238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27238384Sjkim * endorse or promote products derived from this software without 28238384Sjkim * prior written permission. For written permission, please contact 29238384Sjkim * licensing@OpenSSL.org. 30238384Sjkim * 31238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 32238384Sjkim * nor may "OpenSSL" appear in their names without prior written 33238384Sjkim * permission of the OpenSSL Project. 34238384Sjkim * 35238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 36238384Sjkim * acknowledgment: 37238384Sjkim * "This product includes software developed by the OpenSSL Project 38238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39238384Sjkim * 40238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 52238384Sjkim * ==================================================================== 53238384Sjkim * 54238384Sjkim */ 55238384Sjkim 56238384Sjkim#include <openssl/asn1.h> 57238384Sjkim#include <openssl/asn1t.h> 58238384Sjkim#include <openssl/bio.h> 59238384Sjkim#include <openssl/err.h> 60238384Sjkim 61238384Sjkim#include <stdio.h> 62238384Sjkim 63238384Sjkim/* Experimental NDEF ASN1 BIO support routines */ 64238384Sjkim 65296341Sdelphij/* 66296341Sdelphij * The usage is quite simple, initialize an ASN1 structure, get a BIO from it 67296341Sdelphij * then any data written through the BIO will end up translated to 68296341Sdelphij * approptiate format on the fly. The data is streamed out and does *not* 69296341Sdelphij * need to be all held in memory at once. When the BIO is flushed the output 70296341Sdelphij * is finalized and any signatures etc written out. The BIO is a 'proper' 71296341Sdelphij * BIO and can handle non blocking I/O correctly. The usage is simple. The 72296341Sdelphij * implementation is *not*... 73238384Sjkim */ 74238384Sjkim 75238384Sjkim/* BIO support data stored in the ASN1 BIO ex_arg */ 76238384Sjkim 77296341Sdelphijtypedef struct ndef_aux_st { 78296341Sdelphij /* ASN1 structure this BIO refers to */ 79296341Sdelphij ASN1_VALUE *val; 80296341Sdelphij const ASN1_ITEM *it; 81296341Sdelphij /* Top of the BIO chain */ 82296341Sdelphij BIO *ndef_bio; 83296341Sdelphij /* Output BIO */ 84296341Sdelphij BIO *out; 85296341Sdelphij /* Boundary where content is inserted */ 86296341Sdelphij unsigned char **boundary; 87296341Sdelphij /* DER buffer start */ 88296341Sdelphij unsigned char *derbuf; 89296341Sdelphij} NDEF_SUPPORT; 90238384Sjkim 91238384Sjkimstatic int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 92296341Sdelphijstatic int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 93296341Sdelphij void *parg); 94238384Sjkimstatic int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 95296341Sdelphijstatic int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 96296341Sdelphij void *parg); 97238384Sjkim 98238384SjkimBIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 99296341Sdelphij{ 100296341Sdelphij NDEF_SUPPORT *ndef_aux = NULL; 101296341Sdelphij BIO *asn_bio = NULL; 102296341Sdelphij const ASN1_AUX *aux = it->funcs; 103296341Sdelphij ASN1_STREAM_ARG sarg; 104238384Sjkim 105296341Sdelphij if (!aux || !aux->asn1_cb) { 106296341Sdelphij ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 107296341Sdelphij return NULL; 108296341Sdelphij } 109296341Sdelphij ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT)); 110296341Sdelphij asn_bio = BIO_new(BIO_f_asn1()); 111238384Sjkim 112296341Sdelphij /* ASN1 bio needs to be next to output BIO */ 113238384Sjkim 114296341Sdelphij out = BIO_push(asn_bio, out); 115238384Sjkim 116296341Sdelphij if (!ndef_aux || !asn_bio || !out) 117296341Sdelphij goto err; 118238384Sjkim 119296341Sdelphij BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); 120296341Sdelphij BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); 121238384Sjkim 122296341Sdelphij /* 123296341Sdelphij * Now let callback prepend any digest, cipher etc BIOs ASN1 structure 124296341Sdelphij * needs. 125296341Sdelphij */ 126238384Sjkim 127296341Sdelphij sarg.out = out; 128296341Sdelphij sarg.ndef_bio = NULL; 129296341Sdelphij sarg.boundary = NULL; 130238384Sjkim 131296341Sdelphij if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) 132296341Sdelphij goto err; 133238384Sjkim 134296341Sdelphij ndef_aux->val = val; 135296341Sdelphij ndef_aux->it = it; 136296341Sdelphij ndef_aux->ndef_bio = sarg.ndef_bio; 137296341Sdelphij ndef_aux->boundary = sarg.boundary; 138296341Sdelphij ndef_aux->out = out; 139238384Sjkim 140296341Sdelphij BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); 141238384Sjkim 142296341Sdelphij return sarg.ndef_bio; 143238384Sjkim 144296341Sdelphij err: 145296341Sdelphij if (asn_bio) 146296341Sdelphij BIO_free(asn_bio); 147296341Sdelphij if (ndef_aux) 148296341Sdelphij OPENSSL_free(ndef_aux); 149296341Sdelphij return NULL; 150296341Sdelphij} 151238384Sjkim 152238384Sjkimstatic int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 153296341Sdelphij{ 154296341Sdelphij NDEF_SUPPORT *ndef_aux; 155296341Sdelphij unsigned char *p; 156296341Sdelphij int derlen; 157238384Sjkim 158296341Sdelphij if (!parg) 159296341Sdelphij return 0; 160238384Sjkim 161296341Sdelphij ndef_aux = *(NDEF_SUPPORT **)parg; 162238384Sjkim 163296341Sdelphij derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 164296341Sdelphij p = OPENSSL_malloc(derlen); 165296341Sdelphij if (!p) 166296341Sdelphij return 0; 167238384Sjkim 168296341Sdelphij ndef_aux->derbuf = p; 169296341Sdelphij *pbuf = p; 170296341Sdelphij derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 171238384Sjkim 172296341Sdelphij if (!*ndef_aux->boundary) 173296341Sdelphij return 0; 174238384Sjkim 175296341Sdelphij *plen = *ndef_aux->boundary - *pbuf; 176238384Sjkim 177296341Sdelphij return 1; 178296341Sdelphij} 179238384Sjkim 180296341Sdelphijstatic int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 181296341Sdelphij void *parg) 182296341Sdelphij{ 183296341Sdelphij NDEF_SUPPORT *ndef_aux; 184238384Sjkim 185296341Sdelphij if (!parg) 186296341Sdelphij return 0; 187238384Sjkim 188296341Sdelphij ndef_aux = *(NDEF_SUPPORT **)parg; 189238384Sjkim 190296341Sdelphij if (ndef_aux->derbuf) 191296341Sdelphij OPENSSL_free(ndef_aux->derbuf); 192238384Sjkim 193296341Sdelphij ndef_aux->derbuf = NULL; 194296341Sdelphij *pbuf = NULL; 195296341Sdelphij *plen = 0; 196296341Sdelphij return 1; 197296341Sdelphij} 198238384Sjkim 199296341Sdelphijstatic int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 200296341Sdelphij void *parg) 201296341Sdelphij{ 202296341Sdelphij NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; 203296341Sdelphij if (!ndef_prefix_free(b, pbuf, plen, parg)) 204296341Sdelphij return 0; 205296341Sdelphij OPENSSL_free(*pndef_aux); 206296341Sdelphij *pndef_aux = NULL; 207296341Sdelphij return 1; 208296341Sdelphij} 209296341Sdelphij 210238384Sjkimstatic int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 211296341Sdelphij{ 212296341Sdelphij NDEF_SUPPORT *ndef_aux; 213296341Sdelphij unsigned char *p; 214296341Sdelphij int derlen; 215296341Sdelphij const ASN1_AUX *aux; 216296341Sdelphij ASN1_STREAM_ARG sarg; 217238384Sjkim 218296341Sdelphij if (!parg) 219296341Sdelphij return 0; 220238384Sjkim 221296341Sdelphij ndef_aux = *(NDEF_SUPPORT **)parg; 222238384Sjkim 223296341Sdelphij aux = ndef_aux->it->funcs; 224238384Sjkim 225296341Sdelphij /* Finalize structures */ 226296341Sdelphij sarg.ndef_bio = ndef_aux->ndef_bio; 227296341Sdelphij sarg.out = ndef_aux->out; 228296341Sdelphij sarg.boundary = ndef_aux->boundary; 229296341Sdelphij if (aux->asn1_cb(ASN1_OP_STREAM_POST, 230296341Sdelphij &ndef_aux->val, ndef_aux->it, &sarg) <= 0) 231296341Sdelphij return 0; 232238384Sjkim 233296341Sdelphij derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 234296341Sdelphij p = OPENSSL_malloc(derlen); 235296341Sdelphij if (!p) 236296341Sdelphij return 0; 237238384Sjkim 238296341Sdelphij ndef_aux->derbuf = p; 239296341Sdelphij *pbuf = p; 240296341Sdelphij derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 241238384Sjkim 242296341Sdelphij if (!*ndef_aux->boundary) 243296341Sdelphij return 0; 244296341Sdelphij *pbuf = *ndef_aux->boundary; 245296341Sdelphij *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); 246296341Sdelphij 247296341Sdelphij return 1; 248296341Sdelphij} 249