bio_ndef.c 7.3 KB
Newer Older
1 2
/*
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
D
Dr. Stephen Henson 已提交
3 4 5 6 7 8 9 10 11 12
 * project.
 */
/* ====================================================================
 * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
D
Dr. Stephen Henson 已提交
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 */

#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/err.h>

#include <stdio.h>

/* Experimental NDEF ASN1 BIO support routines */

64 65 66
/*
 * The usage is quite simple, initialize an ASN1 structure, get a BIO from it
 * then any data written through the BIO will end up translated to
F
FdaSilvaYY 已提交
67
 * appropriate format on the fly. The data is streamed out and does *not*
68 69 70 71
 * need to be all held in memory at once. When the BIO is flushed the output
 * is finalized and any signatures etc written out. The BIO is a 'proper'
 * BIO and can handle non blocking I/O correctly. The usage is simple. The
 * implementation is *not*...
D
Dr. Stephen Henson 已提交
72 73 74 75
 */

/* BIO support data stored in the ASN1 BIO ex_arg */

76 77 78 79 80 81 82 83 84 85 86 87 88
typedef struct ndef_aux_st {
    /* ASN1 structure this BIO refers to */
    ASN1_VALUE *val;
    const ASN1_ITEM *it;
    /* Top of the BIO chain */
    BIO *ndef_bio;
    /* Output BIO */
    BIO *out;
    /* Boundary where content is inserted */
    unsigned char **boundary;
    /* DER buffer start */
    unsigned char *derbuf;
} NDEF_SUPPORT;
D
Dr. Stephen Henson 已提交
89 90

static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
91 92
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
                            void *parg);
D
Dr. Stephen Henson 已提交
93
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
94 95
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
                            void *parg);
D
Dr. Stephen Henson 已提交
96 97

BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
98 99 100 101 102
{
    NDEF_SUPPORT *ndef_aux = NULL;
    BIO *asn_bio = NULL;
    const ASN1_AUX *aux = it->funcs;
    ASN1_STREAM_ARG sarg;
D
Dr. Stephen Henson 已提交
103

104 105 106 107
    if (!aux || !aux->asn1_cb) {
        ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
        return NULL;
    }
R
Rich Salz 已提交
108
    ndef_aux = OPENSSL_malloc(sizeof(*ndef_aux));
109
    asn_bio = BIO_new(BIO_f_asn1());
D
Dr. Stephen Henson 已提交
110

111
    /* ASN1 bio needs to be next to output BIO */
D
Dr. Stephen Henson 已提交
112

113
    out = BIO_push(asn_bio, out);
D
Dr. Stephen Henson 已提交
114

115
    if (ndef_aux == NULL || asn_bio == NULL || !out)
116
        goto err;
D
Dr. Stephen Henson 已提交
117

118 119
    BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
    BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
D
Dr. Stephen Henson 已提交
120

121
    /*
R
Rich Salz 已提交
122
     * Now let callback prepend any digest, cipher etc BIOs ASN1 structure
123 124
     * needs.
     */
D
Dr. Stephen Henson 已提交
125

126 127 128
    sarg.out = out;
    sarg.ndef_bio = NULL;
    sarg.boundary = NULL;
D
Dr. Stephen Henson 已提交
129

130 131
    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
        goto err;
D
Dr. Stephen Henson 已提交
132

133 134 135 136 137
    ndef_aux->val = val;
    ndef_aux->it = it;
    ndef_aux->ndef_bio = sarg.ndef_bio;
    ndef_aux->boundary = sarg.boundary;
    ndef_aux->out = out;
D
Dr. Stephen Henson 已提交
138

139
    BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
D
Dr. Stephen Henson 已提交
140

141
    return sarg.ndef_bio;
D
Dr. Stephen Henson 已提交
142

143
 err:
R
Rich Salz 已提交
144
    BIO_free(asn_bio);
R
Rich Salz 已提交
145
    OPENSSL_free(ndef_aux);
146 147
    return NULL;
}
D
Dr. Stephen Henson 已提交
148 149

static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
150 151 152 153
{
    NDEF_SUPPORT *ndef_aux;
    unsigned char *p;
    int derlen;
D
Dr. Stephen Henson 已提交
154

155 156
    if (!parg)
        return 0;
D
Dr. Stephen Henson 已提交
157

158
    ndef_aux = *(NDEF_SUPPORT **)parg;
D
Dr. Stephen Henson 已提交
159

160 161
    derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
    p = OPENSSL_malloc(derlen);
162
    if (p == NULL)
M
Matt Caswell 已提交
163 164
        return 0;

165 166 167
    ndef_aux->derbuf = p;
    *pbuf = p;
    derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
D
Dr. Stephen Henson 已提交
168

169 170
    if (!*ndef_aux->boundary)
        return 0;
D
Dr. Stephen Henson 已提交
171

172
    *plen = *ndef_aux->boundary - *pbuf;
D
Dr. Stephen Henson 已提交
173

174 175
    return 1;
}
D
Dr. Stephen Henson 已提交
176

177 178 179 180
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
                            void *parg)
{
    NDEF_SUPPORT *ndef_aux;
D
Dr. Stephen Henson 已提交
181

182 183
    if (!parg)
        return 0;
D
Dr. Stephen Henson 已提交
184

185
    ndef_aux = *(NDEF_SUPPORT **)parg;
D
Dr. Stephen Henson 已提交
186

R
Rich Salz 已提交
187
    OPENSSL_free(ndef_aux->derbuf);
D
Dr. Stephen Henson 已提交
188

189 190 191 192 193
    ndef_aux->derbuf = NULL;
    *pbuf = NULL;
    *plen = 0;
    return 1;
}
D
Dr. Stephen Henson 已提交
194

195 196 197 198 199 200 201 202 203 204
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
                            void *parg)
{
    NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
    if (!ndef_prefix_free(b, pbuf, plen, parg))
        return 0;
    OPENSSL_free(*pndef_aux);
    *pndef_aux = NULL;
    return 1;
}
D
Dr. Stephen Henson 已提交
205 206

static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
{
    NDEF_SUPPORT *ndef_aux;
    unsigned char *p;
    int derlen;
    const ASN1_AUX *aux;
    ASN1_STREAM_ARG sarg;

    if (!parg)
        return 0;

    ndef_aux = *(NDEF_SUPPORT **)parg;

    aux = ndef_aux->it->funcs;

    /* Finalize structures */
    sarg.ndef_bio = ndef_aux->ndef_bio;
    sarg.out = ndef_aux->out;
    sarg.boundary = ndef_aux->boundary;
    if (aux->asn1_cb(ASN1_OP_STREAM_POST,
                     &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
        return 0;

    derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
    p = OPENSSL_malloc(derlen);
231
    if (p == NULL)
M
Matt Caswell 已提交
232 233
        return 0;

234 235 236 237 238 239 240 241 242 243 244
    ndef_aux->derbuf = p;
    *pbuf = p;
    derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);

    if (!*ndef_aux->boundary)
        return 0;
    *pbuf = *ndef_aux->boundary;
    *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);

    return 1;
}