Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/bio_asn1.c
Line
Count
Source (jump to first uncovered line)
1
/* bio_asn1.c */
2
/*
3
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4
 * project.
5
 */
6
/* ====================================================================
7
 * Copyright (c) 2006 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
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
/*
61
 * Experimental ASN1 BIO. When written through the data is converted to an
62
 * ASN1 string type: default is OCTET STRING. Additional functions can be
63
 * provided to add prefix and suffix data.
64
 */
65
66
#include <string.h>
67
#include <openssl/bio.h>
68
#include <openssl/asn1.h>
69
70
/* Must be large enough for biggest tag+length */
71
0
#define DEFAULT_ASN1_BUF_SIZE 20
72
73
typedef enum {
74
    ASN1_STATE_START,
75
    ASN1_STATE_PRE_COPY,
76
    ASN1_STATE_HEADER,
77
    ASN1_STATE_HEADER_COPY,
78
    ASN1_STATE_DATA_COPY,
79
    ASN1_STATE_POST_COPY,
80
    ASN1_STATE_DONE
81
} asn1_bio_state_t;
82
83
typedef struct BIO_ASN1_EX_FUNCS_st {
84
    asn1_ps_func *ex_func;
85
    asn1_ps_func *ex_free_func;
86
} BIO_ASN1_EX_FUNCS;
87
88
typedef struct BIO_ASN1_BUF_CTX_t {
89
    /* Internal state */
90
    asn1_bio_state_t state;
91
    /* Internal buffer */
92
    unsigned char *buf;
93
    /* Size of buffer */
94
    int bufsize;
95
    /* Current position in buffer */
96
    int bufpos;
97
    /* Current buffer length */
98
    int buflen;
99
    /* Amount of data to copy */
100
    int copylen;
101
    /* Class and tag to use */
102
    int asn1_class, asn1_tag;
103
    asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
104
    /* Extra buffer for prefix and suffix data */
105
    unsigned char *ex_buf;
106
    int ex_len;
107
    int ex_pos;
108
    void *ex_arg;
109
} BIO_ASN1_BUF_CTX;
110
111
static int asn1_bio_write(BIO *h, const char *buf, int num);
112
static int asn1_bio_read(BIO *h, char *buf, int size);
113
static int asn1_bio_puts(BIO *h, const char *str);
114
static int asn1_bio_gets(BIO *h, char *str, int size);
115
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
116
static int asn1_bio_new(BIO *h);
117
static int asn1_bio_free(BIO *data);
118
static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
119
120
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
121
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
122
                             asn1_ps_func *cleanup, asn1_bio_state_t next);
123
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
124
                             asn1_ps_func *setup,
125
                             asn1_bio_state_t ex_state,
126
                             asn1_bio_state_t other_state);
127
128
static BIO_METHOD methods_asn1 = {
129
    BIO_TYPE_ASN1,
130
    "asn1",
131
    asn1_bio_write,
132
    asn1_bio_read,
133
    asn1_bio_puts,
134
    asn1_bio_gets,
135
    asn1_bio_ctrl,
136
    asn1_bio_new,
137
    asn1_bio_free,
138
    asn1_bio_callback_ctrl,
139
};
140
141
BIO_METHOD *BIO_f_asn1(void)
142
0
{
143
0
    return (&methods_asn1);
144
0
}
145
146
static int asn1_bio_new(BIO *b)
147
0
{
148
0
    BIO_ASN1_BUF_CTX *ctx;
149
0
    ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
150
0
    if (!ctx)
151
0
        return 0;
152
0
    if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
153
0
        OPENSSL_free(ctx);
154
0
        return 0;
155
0
    }
156
0
    b->init = 1;
157
0
    b->ptr = (char *)ctx;
158
0
    b->flags = 0;
159
0
    return 1;
160
0
}
161
162
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
163
0
{
164
0
    ctx->buf = OPENSSL_malloc(size);
165
0
    if (!ctx->buf)
166
0
        return 0;
167
0
    ctx->bufsize = size;
168
0
    ctx->bufpos = 0;
169
0
    ctx->buflen = 0;
170
0
    ctx->copylen = 0;
171
0
    ctx->asn1_class = V_ASN1_UNIVERSAL;
172
0
    ctx->asn1_tag = V_ASN1_OCTET_STRING;
173
0
    ctx->ex_buf = NULL;
174
0
    ctx->ex_len = 0;
175
0
    ctx->ex_pos = 0;
176
0
    ctx->state = ASN1_STATE_START;
177
0
    ctx->prefix = ctx->prefix_free = ctx->suffix = ctx->suffix_free = NULL;
178
0
    ctx->ex_arg = NULL;
179
0
    return 1;
180
0
}
181
182
static int asn1_bio_free(BIO *b)
183
0
{
184
0
    BIO_ASN1_BUF_CTX *ctx;
185
0
    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
186
0
    if (ctx == NULL)
187
0
        return 0;
188
0
    if (ctx->buf)
189
0
        OPENSSL_free(ctx->buf);
190
0
    OPENSSL_free(ctx);
191
0
    b->init = 0;
192
0
    b->ptr = NULL;
193
0
    b->flags = 0;
194
0
    return 1;
195
0
}
196
197
static int asn1_bio_write(BIO *b, const char *in, int inl)
198
0
{
199
0
    BIO_ASN1_BUF_CTX *ctx;
200
0
    int wrmax, wrlen, ret;
201
0
    unsigned char *p;
202
0
    if (!in || (inl < 0) || (b->next_bio == NULL))
203
0
        return 0;
204
0
    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
205
0
    if (ctx == NULL)
206
0
        return 0;
207
208
0
    wrlen = 0;
209
0
    ret = -1;
210
211
0
    for (;;) {
212
0
        switch (ctx->state) {
213
214
            /* Setup prefix data, call it */
215
0
        case ASN1_STATE_START:
216
0
            if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
217
0
                                   ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
218
0
                return 0;
219
0
            break;
220
221
            /* Copy any pre data first */
222
0
        case ASN1_STATE_PRE_COPY:
223
224
0
            ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
225
0
                                    ASN1_STATE_HEADER);
226
227
0
            if (ret <= 0)
228
0
                goto done;
229
230
0
            break;
231
232
0
        case ASN1_STATE_HEADER:
233
0
            ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
234
0
            OPENSSL_assert(ctx->buflen <= ctx->bufsize);
235
0
            p = ctx->buf;
236
0
            ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
237
0
            ctx->copylen = inl;
238
0
            ctx->state = ASN1_STATE_HEADER_COPY;
239
240
0
            break;
241
242
0
        case ASN1_STATE_HEADER_COPY:
243
0
            ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
244
0
            if (ret <= 0)
245
0
                goto done;
246
247
0
            ctx->buflen -= ret;
248
0
            if (ctx->buflen)
249
0
                ctx->bufpos += ret;
250
0
            else {
251
0
                ctx->bufpos = 0;
252
0
                ctx->state = ASN1_STATE_DATA_COPY;
253
0
            }
254
255
0
            break;
256
257
0
        case ASN1_STATE_DATA_COPY:
258
259
0
            if (inl > ctx->copylen)
260
0
                wrmax = ctx->copylen;
261
0
            else
262
0
                wrmax = inl;
263
0
            ret = BIO_write(b->next_bio, in, wrmax);
264
0
            if (ret <= 0)
265
0
                break;
266
0
            wrlen += ret;
267
0
            ctx->copylen -= ret;
268
0
            in += ret;
269
0
            inl -= ret;
270
271
0
            if (ctx->copylen == 0)
272
0
                ctx->state = ASN1_STATE_HEADER;
273
274
0
            if (inl == 0)
275
0
                goto done;
276
277
0
            break;
278
279
0
        default:
280
0
            BIO_clear_retry_flags(b);
281
0
            return 0;
282
283
0
        }
284
285
0
    }
286
287
0
 done:
288
0
    BIO_clear_retry_flags(b);
289
0
    BIO_copy_next_retry(b);
290
291
0
    return (wrlen > 0) ? wrlen : ret;
292
293
0
}
294
295
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
296
                             asn1_ps_func *cleanup, asn1_bio_state_t next)
297
0
{
298
0
    int ret;
299
0
    if (ctx->ex_len <= 0)
300
0
        return 1;
301
0
    for (;;) {
302
0
        ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos, ctx->ex_len);
303
0
        if (ret <= 0)
304
0
            break;
305
0
        ctx->ex_len -= ret;
306
0
        if (ctx->ex_len > 0)
307
0
            ctx->ex_pos += ret;
308
0
        else {
309
0
            if (cleanup)
310
0
                cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
311
0
            ctx->state = next;
312
0
            ctx->ex_pos = 0;
313
0
            break;
314
0
        }
315
0
    }
316
0
    return ret;
317
0
}
318
319
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
320
                             asn1_ps_func *setup,
321
                             asn1_bio_state_t ex_state,
322
                             asn1_bio_state_t other_state)
323
0
{
324
0
    if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
325
0
        BIO_clear_retry_flags(b);
326
0
        return 0;
327
0
    }
328
0
    if (ctx->ex_len > 0)
329
0
        ctx->state = ex_state;
330
0
    else
331
0
        ctx->state = other_state;
332
0
    return 1;
333
0
}
334
335
static int asn1_bio_read(BIO *b, char *in, int inl)
336
0
{
337
0
    if (!b->next_bio)
338
0
        return 0;
339
0
    return BIO_read(b->next_bio, in, inl);
340
0
}
341
342
static int asn1_bio_puts(BIO *b, const char *str)
343
0
{
344
0
    return asn1_bio_write(b, str, strlen(str));
345
0
}
346
347
static int asn1_bio_gets(BIO *b, char *str, int size)
348
0
{
349
0
    if (!b->next_bio)
350
0
        return 0;
351
0
    return BIO_gets(b->next_bio, str, size);
352
0
}
353
354
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
355
0
{
356
0
    if (b->next_bio == NULL)
357
0
        return (0);
358
0
    return BIO_callback_ctrl(b->next_bio, cmd, fp);
359
0
}
360
361
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
362
0
{
363
0
    BIO_ASN1_BUF_CTX *ctx;
364
0
    BIO_ASN1_EX_FUNCS *ex_func;
365
0
    long ret = 1;
366
0
    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
367
0
    if (ctx == NULL)
368
0
        return 0;
369
0
    switch (cmd) {
370
371
0
    case BIO_C_SET_PREFIX:
372
0
        ex_func = arg2;
373
0
        ctx->prefix = ex_func->ex_func;
374
0
        ctx->prefix_free = ex_func->ex_free_func;
375
0
        break;
376
377
0
    case BIO_C_GET_PREFIX:
378
0
        ex_func = arg2;
379
0
        ex_func->ex_func = ctx->prefix;
380
0
        ex_func->ex_free_func = ctx->prefix_free;
381
0
        break;
382
383
0
    case BIO_C_SET_SUFFIX:
384
0
        ex_func = arg2;
385
0
        ctx->suffix = ex_func->ex_func;
386
0
        ctx->suffix_free = ex_func->ex_free_func;
387
0
        break;
388
389
0
    case BIO_C_GET_SUFFIX:
390
0
        ex_func = arg2;
391
0
        ex_func->ex_func = ctx->suffix;
392
0
        ex_func->ex_free_func = ctx->suffix_free;
393
0
        break;
394
395
0
    case BIO_C_SET_EX_ARG:
396
0
        ctx->ex_arg = arg2;
397
0
        break;
398
399
0
    case BIO_C_GET_EX_ARG:
400
0
        *(void **)arg2 = ctx->ex_arg;
401
0
        break;
402
403
0
    case BIO_CTRL_FLUSH:
404
0
        if (!b->next_bio)
405
0
            return 0;
406
407
        /* Call post function if possible */
408
0
        if (ctx->state == ASN1_STATE_HEADER) {
409
0
            if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
410
0
                                   ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
411
0
                return 0;
412
0
        }
413
414
0
        if (ctx->state == ASN1_STATE_POST_COPY) {
415
0
            ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
416
0
                                    ASN1_STATE_DONE);
417
0
            if (ret <= 0)
418
0
                return ret;
419
0
        }
420
421
0
        if (ctx->state == ASN1_STATE_DONE)
422
0
            return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
423
0
        else {
424
0
            BIO_clear_retry_flags(b);
425
0
            return 0;
426
0
        }
427
0
        break;
428
429
0
    default:
430
0
        if (!b->next_bio)
431
0
            return 0;
432
0
        return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
433
434
0
    }
435
436
0
    return ret;
437
0
}
438
439
static int asn1_bio_set_ex(BIO *b, int cmd,
440
                           asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
441
0
{
442
0
    BIO_ASN1_EX_FUNCS extmp;
443
0
    extmp.ex_func = ex_func;
444
0
    extmp.ex_free_func = ex_free_func;
445
0
    return BIO_ctrl(b, cmd, 0, &extmp);
446
0
}
447
448
static int asn1_bio_get_ex(BIO *b, int cmd,
449
                           asn1_ps_func **ex_func,
450
                           asn1_ps_func **ex_free_func)
451
0
{
452
0
    BIO_ASN1_EX_FUNCS extmp;
453
0
    int ret;
454
0
    ret = BIO_ctrl(b, cmd, 0, &extmp);
455
0
    if (ret > 0) {
456
0
        *ex_func = extmp.ex_func;
457
0
        *ex_free_func = extmp.ex_free_func;
458
0
    }
459
0
    return ret;
460
0
}
461
462
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix,
463
                        asn1_ps_func *prefix_free)
464
0
{
465
0
    return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
466
0
}
467
468
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix,
469
                        asn1_ps_func **pprefix_free)
470
0
{
471
0
    return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
472
0
}
473
474
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix,
475
                        asn1_ps_func *suffix_free)
476
0
{
477
0
    return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
478
0
}
479
480
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix,
481
                        asn1_ps_func **psuffix_free)
482
0
{
483
0
    return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
484
0
}