Coverage Report

Created: 2022-11-30 06:20

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