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