1238384Sjkim/* bio_ndef.c */ 2280304Sjkim/* 3280304Sjkim * 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 14280304Sjkim * 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 65280304Sjkim/* 66280304Sjkim * The usage is quite simple, initialize an ASN1 structure, get a BIO from it 67280304Sjkim * then any data written through the BIO will end up translated to 68280304Sjkim * approptiate format on the fly. The data is streamed out and does *not* 69280304Sjkim * need to be all held in memory at once. When the BIO is flushed the output 70280304Sjkim * is finalized and any signatures etc written out. The BIO is a 'proper' 71280304Sjkim * BIO and can handle non blocking I/O correctly. The usage is simple. The 72280304Sjkim * implementation is *not*... 73238384Sjkim */ 74238384Sjkim 75238384Sjkim/* BIO support data stored in the ASN1 BIO ex_arg */ 76238384Sjkim 77280304Sjkimtypedef struct ndef_aux_st { 78280304Sjkim /* ASN1 structure this BIO refers to */ 79280304Sjkim ASN1_VALUE *val; 80280304Sjkim const ASN1_ITEM *it; 81280304Sjkim /* Top of the BIO chain */ 82280304Sjkim BIO *ndef_bio; 83280304Sjkim /* Output BIO */ 84280304Sjkim BIO *out; 85280304Sjkim /* Boundary where content is inserted */ 86280304Sjkim unsigned char **boundary; 87280304Sjkim /* DER buffer start */ 88280304Sjkim unsigned char *derbuf; 89280304Sjkim} NDEF_SUPPORT; 90238384Sjkim 91238384Sjkimstatic int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 92280304Sjkimstatic int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 93280304Sjkim void *parg); 94238384Sjkimstatic int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); 95280304Sjkimstatic int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 96280304Sjkim void *parg); 97238384Sjkim 98238384SjkimBIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) 99280304Sjkim{ 100280304Sjkim NDEF_SUPPORT *ndef_aux = NULL; 101280304Sjkim BIO *asn_bio = NULL; 102280304Sjkim const ASN1_AUX *aux = it->funcs; 103280304Sjkim ASN1_STREAM_ARG sarg; 104238384Sjkim 105280304Sjkim if (!aux || !aux->asn1_cb) { 106280304Sjkim ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); 107280304Sjkim return NULL; 108280304Sjkim } 109280304Sjkim ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT)); 110280304Sjkim asn_bio = BIO_new(BIO_f_asn1()); 111238384Sjkim 112280304Sjkim /* ASN1 bio needs to be next to output BIO */ 113238384Sjkim 114280304Sjkim out = BIO_push(asn_bio, out); 115238384Sjkim 116280304Sjkim if (!ndef_aux || !asn_bio || !out) 117280304Sjkim goto err; 118238384Sjkim 119280304Sjkim BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); 120280304Sjkim BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); 121238384Sjkim 122280304Sjkim /* 123280304Sjkim * Now let callback prepend any digest, cipher etc BIOs ASN1 structure 124280304Sjkim * needs. 125280304Sjkim */ 126238384Sjkim 127280304Sjkim sarg.out = out; 128280304Sjkim sarg.ndef_bio = NULL; 129280304Sjkim sarg.boundary = NULL; 130238384Sjkim 131280304Sjkim if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) 132280304Sjkim goto err; 133238384Sjkim 134280304Sjkim ndef_aux->val = val; 135280304Sjkim ndef_aux->it = it; 136280304Sjkim ndef_aux->ndef_bio = sarg.ndef_bio; 137280304Sjkim ndef_aux->boundary = sarg.boundary; 138280304Sjkim ndef_aux->out = out; 139238384Sjkim 140280304Sjkim BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); 141238384Sjkim 142280304Sjkim return sarg.ndef_bio; 143238384Sjkim 144280304Sjkim err: 145280304Sjkim if (asn_bio) 146280304Sjkim BIO_free(asn_bio); 147280304Sjkim if (ndef_aux) 148280304Sjkim OPENSSL_free(ndef_aux); 149280304Sjkim return NULL; 150280304Sjkim} 151238384Sjkim 152238384Sjkimstatic int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 153280304Sjkim{ 154280304Sjkim NDEF_SUPPORT *ndef_aux; 155280304Sjkim unsigned char *p; 156280304Sjkim int derlen; 157238384Sjkim 158280304Sjkim if (!parg) 159280304Sjkim return 0; 160238384Sjkim 161280304Sjkim ndef_aux = *(NDEF_SUPPORT **)parg; 162238384Sjkim 163280304Sjkim derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 164280304Sjkim p = OPENSSL_malloc(derlen); 165284285Sjkim if (!p) 166280304Sjkim return 0; 167238384Sjkim 168280304Sjkim ndef_aux->derbuf = p; 169280304Sjkim *pbuf = p; 170280304Sjkim derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 171238384Sjkim 172280304Sjkim if (!*ndef_aux->boundary) 173280304Sjkim return 0; 174238384Sjkim 175280304Sjkim *plen = *ndef_aux->boundary - *pbuf; 176238384Sjkim 177280304Sjkim return 1; 178280304Sjkim} 179238384Sjkim 180280304Sjkimstatic int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, 181280304Sjkim void *parg) 182280304Sjkim{ 183280304Sjkim NDEF_SUPPORT *ndef_aux; 184238384Sjkim 185280304Sjkim if (!parg) 186280304Sjkim return 0; 187238384Sjkim 188280304Sjkim ndef_aux = *(NDEF_SUPPORT **)parg; 189238384Sjkim 190280304Sjkim if (ndef_aux->derbuf) 191280304Sjkim OPENSSL_free(ndef_aux->derbuf); 192238384Sjkim 193280304Sjkim ndef_aux->derbuf = NULL; 194280304Sjkim *pbuf = NULL; 195280304Sjkim *plen = 0; 196280304Sjkim return 1; 197280304Sjkim} 198238384Sjkim 199280304Sjkimstatic int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, 200280304Sjkim void *parg) 201280304Sjkim{ 202280304Sjkim NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; 203280304Sjkim if (!ndef_prefix_free(b, pbuf, plen, parg)) 204280304Sjkim return 0; 205280304Sjkim OPENSSL_free(*pndef_aux); 206280304Sjkim *pndef_aux = NULL; 207280304Sjkim return 1; 208280304Sjkim} 209280304Sjkim 210238384Sjkimstatic int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) 211280304Sjkim{ 212280304Sjkim NDEF_SUPPORT *ndef_aux; 213280304Sjkim unsigned char *p; 214280304Sjkim int derlen; 215280304Sjkim const ASN1_AUX *aux; 216280304Sjkim ASN1_STREAM_ARG sarg; 217238384Sjkim 218280304Sjkim if (!parg) 219280304Sjkim return 0; 220238384Sjkim 221280304Sjkim ndef_aux = *(NDEF_SUPPORT **)parg; 222238384Sjkim 223280304Sjkim aux = ndef_aux->it->funcs; 224238384Sjkim 225280304Sjkim /* Finalize structures */ 226280304Sjkim sarg.ndef_bio = ndef_aux->ndef_bio; 227280304Sjkim sarg.out = ndef_aux->out; 228280304Sjkim sarg.boundary = ndef_aux->boundary; 229280304Sjkim if (aux->asn1_cb(ASN1_OP_STREAM_POST, 230280304Sjkim &ndef_aux->val, ndef_aux->it, &sarg) <= 0) 231280304Sjkim return 0; 232238384Sjkim 233280304Sjkim derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); 234280304Sjkim p = OPENSSL_malloc(derlen); 235284285Sjkim if (!p) 236280304Sjkim return 0; 237238384Sjkim 238280304Sjkim ndef_aux->derbuf = p; 239280304Sjkim *pbuf = p; 240280304Sjkim derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); 241238384Sjkim 242280304Sjkim if (!*ndef_aux->boundary) 243280304Sjkim return 0; 244280304Sjkim *pbuf = *ndef_aux->boundary; 245280304Sjkim *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); 246280304Sjkim 247280304Sjkim return 1; 248280304Sjkim} 249