Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/asn1/asn1_par.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include <openssl/buffer.h>
13
#include <openssl/objects.h>
14
#include <openssl/asn1.h>
15
16
#ifndef ASN1_PARSE_MAXDEPTH
17
0
#define ASN1_PARSE_MAXDEPTH 128
18
#endif
19
20
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
21
                           int indent);
22
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
23
                       int offset, int depth, int indent, int dump);
24
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
25
                           int indent)
26
0
{
27
0
    static const char fmt[] = "%-18s";
28
0
    char str[128];
29
0
    const char *p;
30
0
31
0
    if (constructed & V_ASN1_CONSTRUCTED)
32
0
        p = "cons: ";
33
0
    else
34
0
        p = "prim: ";
35
0
    if (BIO_write(bp, p, 6) < 6)
36
0
        goto err;
37
0
    BIO_indent(bp, indent, 128);
38
0
39
0
    p = str;
40
0
    if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
41
0
        BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
42
0
    else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
43
0
        BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
44
0
    else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
45
0
        BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
46
0
    else if (tag > 30)
47
0
        BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
48
0
    else
49
0
        p = ASN1_tag2str(tag);
50
0
51
0
    if (BIO_printf(bp, fmt, p) <= 0)
52
0
        goto err;
53
0
    return 1;
54
0
 err:
55
0
    return 0;
56
0
}
57
58
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
59
0
{
60
0
    return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
61
0
}
62
63
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
64
                    int dump)
65
0
{
66
0
    return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
67
0
}
68
69
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
70
                       int offset, int depth, int indent, int dump)
71
0
{
72
0
    const unsigned char *p, *ep, *tot, *op, *opp;
73
0
    long len;
74
0
    int tag, xclass, ret = 0;
75
0
    int nl, hl, j, r;
76
0
    ASN1_OBJECT *o = NULL;
77
0
    ASN1_OCTET_STRING *os = NULL;
78
0
    /* ASN1_BMPSTRING *bmp=NULL; */
79
0
    int dump_indent, dump_cont = 0;
80
0
81
0
    if (depth > ASN1_PARSE_MAXDEPTH) {
82
0
        BIO_puts(bp, "BAD RECURSION DEPTH\n");
83
0
        return 0;
84
0
    }
85
0
86
0
    dump_indent = 6;            /* Because we know BIO_dump_indent() */
87
0
    p = *pp;
88
0
    tot = p + length;
89
0
    while (length > 0) {
90
0
        op = p;
91
0
        j = ASN1_get_object(&p, &len, &tag, &xclass, length);
92
0
        if (j & 0x80) {
93
0
            if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
94
0
                goto end;
95
0
            ret = 0;
96
0
            goto end;
97
0
        }
98
0
        hl = (p - op);
99
0
        length -= hl;
100
0
        /*
101
0
         * if j == 0x21 it is a constructed indefinite length object
102
0
         */
103
0
        if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
104
0
            <= 0)
105
0
            goto end;
106
0
107
0
        if (j != (V_ASN1_CONSTRUCTED | 1)) {
108
0
            if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
109
0
                           depth, (long)hl, len) <= 0)
110
0
                goto end;
111
0
        } else {
112
0
            if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ", depth, (long)hl) <= 0)
113
0
                goto end;
114
0
        }
115
0
        if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
116
0
            goto end;
117
0
        if (j & V_ASN1_CONSTRUCTED) {
118
0
            const unsigned char *sp = p;
119
0
120
0
            ep = p + len;
121
0
            if (BIO_write(bp, "\n", 1) <= 0)
122
0
                goto end;
123
0
            if (len > length) {
124
0
                BIO_printf(bp, "length is greater than %ld\n", length);
125
0
                ret = 0;
126
0
                goto end;
127
0
            }
128
0
            if ((j == 0x21) && (len == 0)) {
129
0
                for (;;) {
130
0
                    r = asn1_parse2(bp, &p, (long)(tot - p),
131
0
                                    offset + (p - *pp), depth + 1,
132
0
                                    indent, dump);
133
0
                    if (r == 0) {
134
0
                        ret = 0;
135
0
                        goto end;
136
0
                    }
137
0
                    if ((r == 2) || (p >= tot)) {
138
0
                        len = p - sp;
139
0
                        break;
140
0
                    }
141
0
                }
142
0
            } else {
143
0
                long tmp = len;
144
0
145
0
                while (p < ep) {
146
0
                    sp = p;
147
0
                    r = asn1_parse2(bp, &p, tmp,
148
0
                                    offset + (p - *pp), depth + 1,
149
0
                                    indent, dump);
150
0
                    if (r == 0) {
151
0
                        ret = 0;
152
0
                        goto end;
153
0
                    }
154
0
                    tmp -= p - sp;
155
0
                }
156
0
            }
157
0
        } else if (xclass != 0) {
158
0
            p += len;
159
0
            if (BIO_write(bp, "\n", 1) <= 0)
160
0
                goto end;
161
0
        } else {
162
0
            nl = 0;
163
0
            if ((tag == V_ASN1_PRINTABLESTRING) ||
164
0
                (tag == V_ASN1_T61STRING) ||
165
0
                (tag == V_ASN1_IA5STRING) ||
166
0
                (tag == V_ASN1_VISIBLESTRING) ||
167
0
                (tag == V_ASN1_NUMERICSTRING) ||
168
0
                (tag == V_ASN1_UTF8STRING) ||
169
0
                (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
170
0
                if (BIO_write(bp, ":", 1) <= 0)
171
0
                    goto end;
172
0
                if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
173
0
                    != (int)len)
174
0
                    goto end;
175
0
            } else if (tag == V_ASN1_OBJECT) {
176
0
                opp = op;
177
0
                if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
178
0
                    if (BIO_write(bp, ":", 1) <= 0)
179
0
                        goto end;
180
0
                    i2a_ASN1_OBJECT(bp, o);
181
0
                } else {
182
0
                    if (BIO_puts(bp, ":BAD OBJECT") <= 0)
183
0
                        goto end;
184
0
                    dump_cont = 1;
185
0
                }
186
0
            } else if (tag == V_ASN1_BOOLEAN) {
187
0
                if (len != 1) {
188
0
                    if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
189
0
                        goto end;
190
0
                    dump_cont = 1;
191
0
                }
192
0
                if (len > 0)
193
0
                    BIO_printf(bp, ":%u", p[0]);
194
0
            } else if (tag == V_ASN1_BMPSTRING) {
195
0
                /* do the BMP thang */
196
0
            } else if (tag == V_ASN1_OCTET_STRING) {
197
0
                int i, printable = 1;
198
0
199
0
                opp = op;
200
0
                os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
201
0
                if (os != NULL && os->length > 0) {
202
0
                    opp = os->data;
203
0
                    /*
204
0
                     * testing whether the octet string is printable
205
0
                     */
206
0
                    for (i = 0; i < os->length; i++) {
207
0
                        if (((opp[i] < ' ') &&
208
0
                             (opp[i] != '\n') &&
209
0
                             (opp[i] != '\r') &&
210
0
                             (opp[i] != '\t')) || (opp[i] > '~')) {
211
0
                            printable = 0;
212
0
                            break;
213
0
                        }
214
0
                    }
215
0
                    if (printable)
216
0
                        /* printable string */
217
0
                    {
218
0
                        if (BIO_write(bp, ":", 1) <= 0)
219
0
                            goto end;
220
0
                        if (BIO_write(bp, (const char *)opp, os->length) <= 0)
221
0
                            goto end;
222
0
                    } else if (!dump)
223
0
                        /*
224
0
                         * not printable => print octet string as hex dump
225
0
                         */
226
0
                    {
227
0
                        if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
228
0
                            goto end;
229
0
                        for (i = 0; i < os->length; i++) {
230
0
                            if (BIO_printf(bp, "%02X", opp[i]) <= 0)
231
0
                                goto end;
232
0
                        }
233
0
                    } else
234
0
                        /* print the normal dump */
235
0
                    {
236
0
                        if (!nl) {
237
0
                            if (BIO_write(bp, "\n", 1) <= 0)
238
0
                                goto end;
239
0
                        }
240
0
                        if (BIO_dump_indent(bp,
241
0
                                            (const char *)opp,
242
0
                                            ((dump == -1 || dump >
243
0
                                              os->
244
0
                                              length) ? os->length : dump),
245
0
                                            dump_indent) <= 0)
246
0
                            goto end;
247
0
                        nl = 1;
248
0
                    }
249
0
                }
250
0
                ASN1_OCTET_STRING_free(os);
251
0
                os = NULL;
252
0
            } else if (tag == V_ASN1_INTEGER) {
253
0
                ASN1_INTEGER *bs;
254
0
                int i;
255
0
256
0
                opp = op;
257
0
                bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
258
0
                if (bs != NULL) {
259
0
                    if (BIO_write(bp, ":", 1) <= 0)
260
0
                        goto end;
261
0
                    if (bs->type == V_ASN1_NEG_INTEGER)
262
0
                        if (BIO_write(bp, "-", 1) <= 0)
263
0
                            goto end;
264
0
                    for (i = 0; i < bs->length; i++) {
265
0
                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
266
0
                            goto end;
267
0
                    }
268
0
                    if (bs->length == 0) {
269
0
                        if (BIO_write(bp, "00", 2) <= 0)
270
0
                            goto end;
271
0
                    }
272
0
                } else {
273
0
                    if (BIO_puts(bp, ":BAD INTEGER") <= 0)
274
0
                        goto end;
275
0
                    dump_cont = 1;
276
0
                }
277
0
                ASN1_INTEGER_free(bs);
278
0
            } else if (tag == V_ASN1_ENUMERATED) {
279
0
                ASN1_ENUMERATED *bs;
280
0
                int i;
281
0
282
0
                opp = op;
283
0
                bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
284
0
                if (bs != NULL) {
285
0
                    if (BIO_write(bp, ":", 1) <= 0)
286
0
                        goto end;
287
0
                    if (bs->type == V_ASN1_NEG_ENUMERATED)
288
0
                        if (BIO_write(bp, "-", 1) <= 0)
289
0
                            goto end;
290
0
                    for (i = 0; i < bs->length; i++) {
291
0
                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0)
292
0
                            goto end;
293
0
                    }
294
0
                    if (bs->length == 0) {
295
0
                        if (BIO_write(bp, "00", 2) <= 0)
296
0
                            goto end;
297
0
                    }
298
0
                } else {
299
0
                    if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
300
0
                        goto end;
301
0
                    dump_cont = 1;
302
0
                }
303
0
                ASN1_ENUMERATED_free(bs);
304
0
            } else if (len > 0 && dump) {
305
0
                if (!nl) {
306
0
                    if (BIO_write(bp, "\n", 1) <= 0)
307
0
                        goto end;
308
0
                }
309
0
                if (BIO_dump_indent(bp, (const char *)p,
310
0
                                    ((dump == -1 || dump > len) ? len : dump),
311
0
                                    dump_indent) <= 0)
312
0
                    goto end;
313
0
                nl = 1;
314
0
            }
315
0
            if (dump_cont) {
316
0
                int i;
317
0
                const unsigned char *tmp = op + hl;
318
0
                if (BIO_puts(bp, ":[") <= 0)
319
0
                    goto end;
320
0
                for (i = 0; i < len; i++) {
321
0
                    if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
322
0
                        goto end;
323
0
                }
324
0
                if (BIO_puts(bp, "]") <= 0)
325
0
                    goto end;
326
0
            }
327
0
328
0
            if (!nl) {
329
0
                if (BIO_write(bp, "\n", 1) <= 0)
330
0
                    goto end;
331
0
            }
332
0
            p += len;
333
0
            if ((tag == V_ASN1_EOC) && (xclass == 0)) {
334
0
                ret = 2;        /* End of sequence */
335
0
                goto end;
336
0
            }
337
0
        }
338
0
        length -= len;
339
0
    }
340
0
    ret = 1;
341
0
 end:
342
0
    ASN1_OBJECT_free(o);
343
0
    ASN1_OCTET_STRING_free(os);
344
0
    *pp = p;
345
0
    return ret;
346
0
}
347
348
const char *ASN1_tag2str(int tag)
349
0
{
350
0
    static const char *const tag2str[] = {
351
0
        /* 0-4 */
352
0
        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
353
0
        /* 5-9 */
354
0
        "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
355
0
        /* 10-13 */
356
0
        "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
357
0
        /* 15-17 */
358
0
        "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
359
0
        /* 18-20 */
360
0
        "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
361
0
        /* 21-24 */
362
0
        "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
363
0
        /* 25-27 */
364
0
        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
365
0
        /* 28-30 */
366
0
        "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
367
0
    };
368
0
369
0
    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
370
0
        tag &= ~0x100;
371
0
372
0
    if (tag < 0 || tag > 30)
373
0
        return "(unknown)";
374
0
    return tag2str[tag];
375
0
}