Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/asn1_par.c
Line
Count
Source (jump to first uncovered line)
1
/* crypto/asn1/asn1_par.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3
 * All rights reserved.
4
 *
5
 * This package is an SSL implementation written
6
 * by Eric Young (eay@cryptsoft.com).
7
 * The implementation was written so as to conform with Netscapes SSL.
8
 *
9
 * This library is free for commercial and non-commercial use as long as
10
 * the following conditions are aheared to.  The following conditions
11
 * apply to all code found in this distribution, be it the RC4, RSA,
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13
 * included with this distribution is covered by the same copyright terms
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15
 *
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
17
 * the code are not to be removed.
18
 * If this package is used in a product, Eric Young should be given attribution
19
 * as the author of the parts of the library used.
20
 * This can be in the form of a textual message at program startup or
21
 * in documentation (online or textual) provided with the package.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 * 1. Redistributions of source code must retain the copyright
27
 *    notice, this list of conditions and the following disclaimer.
28
 * 2. Redistributions in binary form must reproduce the above copyright
29
 *    notice, this list of conditions and the following disclaimer in the
30
 *    documentation and/or other materials provided with the distribution.
31
 * 3. All advertising materials mentioning features or use of this software
32
 *    must display the following acknowledgement:
33
 *    "This product includes cryptographic software written by
34
 *     Eric Young (eay@cryptsoft.com)"
35
 *    The word 'cryptographic' can be left out if the rouines from the library
36
 *    being used are not cryptographic related :-).
37
 * 4. If you include any Windows specific code (or a derivative thereof) from
38
 *    the apps directory (application code) you must include an acknowledgement:
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 *
53
 * The licence and distribution terms for any publically available version or
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55
 * copied and put under another distribution licence
56
 * [including the GNU Public Licence.]
57
 */
58
59
#include <stdio.h>
60
#include "cryptlib.h"
61
#include <openssl/buffer.h>
62
#include <openssl/objects.h>
63
#include <openssl/asn1.h>
64
65
#ifndef ASN1_PARSE_MAXDEPTH
66
0
#define ASN1_PARSE_MAXDEPTH 128
67
#endif
68
69
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
70
                           int indent);
71
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
72
                       int offset, int depth, int indent, int dump);
73
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
74
                           int indent)
75
0
{
76
0
    static const char fmt[] = "%-18s";
77
0
    char str[128];
78
0
    const char *p;
79
80
0
    if (constructed & V_ASN1_CONSTRUCTED)
81
0
        p = "cons: ";
82
0
    else
83
0
        p = "prim: ";
84
0
    if (BIO_write(bp, p, 6) < 6)
85
0
        goto err;
86
0
    BIO_indent(bp, indent, 128);
87
88
0
    p = str;
89
0
    if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
90
0
        BIO_snprintf(str, sizeof str, "priv [ %d ] ", tag);
91
0
    else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
92
0
        BIO_snprintf(str, sizeof str, "cont [ %d ]", tag);
93
0
    else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
94
0
        BIO_snprintf(str, sizeof str, "appl [ %d ]", tag);
95
0
    else if (tag > 30)
96
0
        BIO_snprintf(str, sizeof str, "<ASN1 %d>", tag);
97
0
    else
98
0
        p = ASN1_tag2str(tag);
99
100
0
    if (BIO_printf(bp, fmt, p) <= 0)
101
0
        goto err;
102
0
    return (1);
103
0
 err:
104
0
    return (0);
105
0
}
106
107
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
108
0
{
109
0
    return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
110
0
}
111
112
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
113
                    int dump)
114
0
{
115
0
    return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
116
0
}
117
118
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
119
                       int offset, int depth, int indent, int dump)
120
0
{
121
0
    const unsigned char *p, *ep, *tot, *op, *opp;
122
0
    long len;
123
0
    int tag, xclass, ret = 0;
124
0
    int nl, hl, j, r;
125
0
    ASN1_OBJECT *o = NULL;
126
0
    ASN1_OCTET_STRING *os = NULL;
127
    /* ASN1_BMPSTRING *bmp=NULL; */
128
0
    int dump_indent;
129
130
#if 0
131
    dump_indent = indent;
132
#else
133
0
    dump_indent = 6;            /* Because we know BIO_dump_indent() */
134
0
#endif
135
136
0
    if (depth > ASN1_PARSE_MAXDEPTH) {
137
0
            BIO_puts(bp, "BAD RECURSION DEPTH\n");
138
0
            return 0;
139
0
    }
140
141
0
    p = *pp;
142
0
    tot = p + length;
143
0
    op = p - 1;
144
0
    while ((p < tot) && (op < p)) {
145
0
        op = p;
146
0
        j = ASN1_get_object(&p, &len, &tag, &xclass, length);
147
#ifdef LINT
148
        j = j;
149
#endif
150
0
        if (j & 0x80) {
151
0
            if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
152
0
                goto end;
153
0
            ret = 0;
154
0
            goto end;
155
0
        }
156
0
        hl = (p - op);
157
0
        length -= hl;
158
        /*
159
         * if j == 0x21 it is a constructed indefinite length object
160
         */
161
0
        if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
162
0
            <= 0)
163
0
            goto end;
164
165
0
        if (j != (V_ASN1_CONSTRUCTED | 1)) {
166
0
            if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
167
0
                           depth, (long)hl, len) <= 0)
168
0
                goto end;
169
0
        } else {
170
0
            if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ", depth, (long)hl) <= 0)
171
0
                goto end;
172
0
        }
173
0
        if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
174
0
            goto end;
175
0
        if (j & V_ASN1_CONSTRUCTED) {
176
0
            const unsigned char *sp;
177
178
0
            ep = p + len;
179
0
            if (BIO_write(bp, "\n", 1) <= 0)
180
0
                goto end;
181
0
            if (len > length) {
182
0
                BIO_printf(bp, "length is greater than %ld\n", length);
183
0
                ret = 0;
184
0
                goto end;
185
0
            }
186
0
            if ((j == 0x21) && (len == 0)) {
187
0
                sp = p;
188
0
                for (;;) {
189
0
                    r = asn1_parse2(bp, &p, (long)(tot - p),
190
0
                                    offset + (p - *pp), depth + 1,
191
0
                                    indent, dump);
192
0
                    if (r == 0) {
193
0
                        ret = 0;
194
0
                        goto end;
195
0
                    }
196
0
                    if ((r == 2) || (p >= tot)) {
197
0
                        len = p - sp;
198
0
                        break;
199
0
                    }
200
0
                }
201
0
            } else {
202
0
                long tmp = len;
203
204
0
                while (p < ep) {
205
0
                    sp = p;
206
0
                    r = asn1_parse2(bp, &p, tmp, offset + (p - *pp), depth + 1,
207
0
                                    indent, dump);
208
0
                    if (r == 0) {
209
0
                        ret = 0;
210
0
                        goto end;
211
0
                    }
212
0
                    tmp -= p - sp;
213
0
                }
214
0
            }
215
0
        } else if (xclass != 0) {
216
0
            p += len;
217
0
            if (BIO_write(bp, "\n", 1) <= 0)
218
0
                goto end;
219
0
        } else {
220
0
            nl = 0;
221
0
            if ((tag == V_ASN1_PRINTABLESTRING) ||
222
0
                (tag == V_ASN1_T61STRING) ||
223
0
                (tag == V_ASN1_IA5STRING) ||
224
0
                (tag == V_ASN1_VISIBLESTRING) ||
225
0
                (tag == V_ASN1_NUMERICSTRING) ||
226
0
                (tag == V_ASN1_UTF8STRING) ||
227
0
                (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
228
0
                if (BIO_write(bp, ":", 1) <= 0)
229
0
                    goto end;
230
0
                if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
231
0
                    != (int)len)
232
0
                    goto end;
233
0
            } else if (tag == V_ASN1_OBJECT) {
234
0
                opp = op;
235
0
                if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
236
0
                    if (BIO_write(bp, ":", 1) <= 0)
237
0
                        goto end;
238
0
                    i2a_ASN1_OBJECT(bp, o);
239
0
                } else {
240
0
                    if (BIO_write(bp, ":BAD OBJECT", 11) <= 0)
241
0
                        goto end;
242
0
                }
243
0
            } else if (tag == V_ASN1_BOOLEAN) {
244
0
                int ii;
245
246
0
                opp = op;
247
0
                ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
248
0
                if (ii < 0) {
249
0
                    if (BIO_write(bp, "Bad boolean\n", 12) <= 0)
250
0
                        goto end;
251
0
                }
252
0
                BIO_printf(bp, ":%d", ii);
253
0
            } else if (tag == V_ASN1_BMPSTRING) {
254
                /* do the BMP thang */
255
0
            } else if (tag == V_ASN1_OCTET_STRING) {
256
0
                int i, printable = 1;
257
258
0
                opp = op;
259
0
                os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
260
0
                if (os != NULL && os->length > 0) {
261
0
                    opp = os->data;
262
                    /*
263
                     * testing whether the octet string is printable
264
                     */
265
0
                    for (i = 0; i < os->length; i++) {
266
0
                        if (((opp[i] < ' ') &&
267
0
                             (opp[i] != '\n') &&
268
0
                             (opp[i] != '\r') &&
269
0
                             (opp[i] != '\t')) || (opp[i] > '~')) {
270
0
                            printable = 0;
271
0
                            break;
272
0
                        }
273
0
                    }
274
0
                    if (printable)
275
                        /* printable string */
276
0
                    {
277
0
                        if (BIO_write(bp, ":", 1) <= 0)
278
0
                            goto end;
279
0
                        if (BIO_write(bp, (const char *)opp, os->length) <= 0)
280
0
                            goto end;
281
0
                    } else if (!dump)
282
                        /*
283
                         * not printable => print octet string as hex dump
284
                         */
285
0
                    {
286
0
                        if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
287
0
                            goto end;
288
0
                        for (i = 0; i < os->length; i++) {
289
0
                            if (BIO_printf(bp, "%02X", opp[i]) <= 0)
290
0
                                goto end;
291
0
                        }
292
0
                    } else
293
                        /* print the normal dump */
294
0
                    {
295
0
                        if (!nl) {
296
0
                            if (BIO_write(bp, "\n", 1) <= 0)
297
0
                                goto end;
298
0
                        }
299
0
                        if (BIO_dump_indent(bp,
300
0
                                            (const char *)opp,
301
0
                                            ((dump == -1 || dump >
302
0
                                              os->
303
0
                                              length) ? os->length : dump),
304
0
                                            dump_indent) <= 0)
305
0
                            goto end;
306
0
                        nl = 1;
307
0
                    }
308
0
                }
309
0
                if (os != NULL) {
310
0
                    M_ASN1_OCTET_STRING_free(os);
311
0
                    os = NULL;
312
0
                }
313
0
            } else if (tag == V_ASN1_INTEGER) {
314
0
                ASN1_INTEGER *bs;
315
0
                int i;
316
317
0
                opp = op;
318
0
                bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
319
0
                if (bs != NULL) {
320
0
                    if (BIO_write(bp, ":", 1) <= 0)
321
0
                        goto end;
322
0
                    if (bs->type == V_ASN1_NEG_INTEGER)
323
0
                        if (BIO_write(bp, "-", 1) <= 0)
324
0
                            goto end;
325
0
                    for (i = 0; i < bs->length; i++) {
326
0
                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
327
0
                            goto end;
328
0
                    }
329
0
                    if (bs->length == 0) {
330
0
                        if (BIO_write(bp, "00", 2) <= 0)
331
0
                            goto end;
332
0
                    }
333
0
                } else {
334
0
                    if (BIO_write(bp, "BAD INTEGER", 11) <= 0)
335
0
                        goto end;
336
0
                }
337
0
                M_ASN1_INTEGER_free(bs);
338
0
            } else if (tag == V_ASN1_ENUMERATED) {
339
0
                ASN1_ENUMERATED *bs;
340
0
                int i;
341
342
0
                opp = op;
343
0
                bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
344
0
                if (bs != NULL) {
345
0
                    if (BIO_write(bp, ":", 1) <= 0)
346
0
                        goto end;
347
0
                    if (bs->type == V_ASN1_NEG_ENUMERATED)
348
0
                        if (BIO_write(bp, "-", 1) <= 0)
349
0
                            goto end;
350
0
                    for (i = 0; i < bs->length; i++) {
351
0
                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
352
0
                            goto end;
353
0
                    }
354
0
                    if (bs->length == 0) {
355
0
                        if (BIO_write(bp, "00", 2) <= 0)
356
0
                            goto end;
357
0
                    }
358
0
                } else {
359
0
                    if (BIO_write(bp, "BAD ENUMERATED", 14) <= 0)
360
0
                        goto end;
361
0
                }
362
0
                M_ASN1_ENUMERATED_free(bs);
363
0
            } else if (len > 0 && dump) {
364
0
                if (!nl) {
365
0
                    if (BIO_write(bp, "\n", 1) <= 0)
366
0
                        goto end;
367
0
                }
368
0
                if (BIO_dump_indent(bp, (const char *)p,
369
0
                                    ((dump == -1 || dump > len) ? len : dump),
370
0
                                    dump_indent) <= 0)
371
0
                    goto end;
372
0
                nl = 1;
373
0
            }
374
375
0
            if (!nl) {
376
0
                if (BIO_write(bp, "\n", 1) <= 0)
377
0
                    goto end;
378
0
            }
379
0
            p += len;
380
0
            if ((tag == V_ASN1_EOC) && (xclass == 0)) {
381
0
                ret = 2;        /* End of sequence */
382
0
                goto end;
383
0
            }
384
0
        }
385
0
        length -= len;
386
0
    }
387
0
    ret = 1;
388
0
 end:
389
0
    if (o != NULL)
390
0
        ASN1_OBJECT_free(o);
391
0
    if (os != NULL)
392
0
        M_ASN1_OCTET_STRING_free(os);
393
0
    *pp = p;
394
0
    return (ret);
395
0
}
396
397
const char *ASN1_tag2str(int tag)
398
0
{
399
0
    static const char *const tag2str[] = {
400
        /* 0-4 */
401
0
        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
402
        /* 5-9 */
403
0
        "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
404
        /* 10-13 */
405
0
        "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
406
        /* 15-17 */
407
0
        "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
408
        /* 18-20 */
409
0
        "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
410
        /* 21-24 */
411
0
        "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
412
        /* 25-27 */
413
0
        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
414
        /* 28-30 */
415
0
        "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
416
0
    };
417
418
0
    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
419
0
        tag &= ~0x100;
420
421
0
    if (tag < 0 || tag > 30)
422
0
        return "(unknown)";
423
0
    return tag2str[tag];
424
0
}