GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/asn1/asn1_par.c Lines: 41 189 21.7 %
Date: 2017-11-07 Branches: 17 196 8.7 %

Line Branch Exec Source
1
/* $OpenBSD: asn1_par.c,v 1.25 2015/09/30 19:01:14 jsing Exp $ */
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
61
#include <openssl/asn1.h>
62
#include <openssl/buffer.h>
63
#include <openssl/objects.h>
64
65
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
66
    int indent);
67
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
68
    int offset, int depth, int indent, int dump);
69
70
static int
71
asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
72
    int indent)
73
{
74
4
	char str[128];
75
	const char *p;
76
77
2
	if (constructed & V_ASN1_CONSTRUCTED)
78
		p="cons: ";
79
	else
80
		p="prim: ";
81
2
	if (BIO_write(bp, p, 6) < 6)
82
		goto err;
83
2
	BIO_indent(bp, indent, 128);
84
85
2
	p = str;
86
2
	if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
87
		snprintf(str, sizeof str, "priv [ %d ] ", tag);
88
2
	else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
89
2
		snprintf(str, sizeof str, "cont [ %d ]", tag);
90
	else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
91
		snprintf(str, sizeof str, "appl [ %d ]", tag);
92
	else if (tag > 30)
93
		snprintf(str, sizeof str, "<ASN1 %d>", tag);
94
	else
95
		p = ASN1_tag2str(tag);
96
97
2
	if (BIO_printf(bp, "%-18s", p) <= 0)
98
		goto err;
99
2
	return (1);
100
err:
101
	return (0);
102
2
}
103
104
int
105
ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
106
{
107
	return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
108
}
109
110
int
111
ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
112
{
113
2
	return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
114
}
115
116
static int
117
asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
118
    int depth, int indent, int dump)
119
{
120
4
	const unsigned char *p, *ep, *tot, *op, *opp;
121
2
	long len;
122
2
	int tag, xclass, ret = 0;
123
	int nl, hl, j, r;
124
2
	ASN1_OBJECT *o = NULL;
125
	ASN1_OCTET_STRING *os = NULL;
126
	/* ASN1_BMPSTRING *bmp=NULL;*/
127
	int dump_indent;
128
129
	dump_indent = 6;	/* Because we know BIO_dump_indent() */
130
2
	p = *pp;
131
2
	tot = p + length;
132
2
	op = p - 1;
133

10
	while ((p < tot) && (op < p)) {
134
		op = p;
135
2
		j = ASN1_get_object(&p, &len, &tag, &xclass, length);
136
137
2
		if (j & 0x80) {
138
			if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
139
				goto end;
140
			ret = 0;
141
			goto end;
142
		}
143
2
		hl = (p - op);
144
2
		length -= hl;
145
		/* if j == 0x21 it is a constructed indefinite length object */
146
6
		if (BIO_printf(bp, "%5ld:", (long)offset +
147
4
		    (long)(op - *pp)) <= 0)
148
		    goto end;
149
150
2
		if (j != (V_ASN1_CONSTRUCTED | 1)) {
151
4
			if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
152
4
			    depth, (long)hl, len) <= 0)
153
				goto end;
154
		} else {
155
			if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ",
156
			    depth, (long)hl) <= 0)
157
				goto end;
158
		}
159
2
		if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
160
			goto end;
161
2
		if (j & V_ASN1_CONSTRUCTED) {
162
			ep = p + len;
163
			if (BIO_write(bp, "\n", 1) <= 0)
164
				goto end;
165
			if (len > length) {
166
				BIO_printf(bp, "length is greater than %ld\n",
167
				    length);
168
				ret = 0;
169
				goto end;
170
			}
171
			if ((j == 0x21) && (len == 0)) {
172
				for (;;) {
173
					r = asn1_parse2(bp, &p, (long)(tot - p),
174
					    offset + (p - *pp), depth + 1,
175
					    indent, dump);
176
					if (r == 0) {
177
						ret = 0;
178
						goto end;
179
					}
180
					if ((r == 2) || (p >= tot))
181
						break;
182
				}
183
			} else
184
				while (p < ep) {
185
					r = asn1_parse2(bp, &p, (long)len,
186
					    offset + (p - *pp), depth + 1,
187
					    indent, dump);
188
					if (r == 0) {
189
						ret = 0;
190
						goto end;
191
					}
192
				}
193
2
		} else if (xclass != 0) {
194
2
			p += len;
195
2
			if (BIO_write(bp, "\n", 1) <= 0)
196
				goto end;
197
		} else {
198
			nl = 0;
199
			if ((tag == V_ASN1_PRINTABLESTRING) ||
200
			    (tag == V_ASN1_T61STRING) ||
201
			    (tag == V_ASN1_IA5STRING) ||
202
			    (tag == V_ASN1_VISIBLESTRING) ||
203
			    (tag == V_ASN1_NUMERICSTRING) ||
204
			    (tag == V_ASN1_UTF8STRING) ||
205
			    (tag == V_ASN1_UTCTIME) ||
206
			    (tag == V_ASN1_GENERALIZEDTIME)) {
207
				if (BIO_write(bp, ":", 1) <= 0)
208
					goto end;
209
				if ((len > 0) &&
210
				    BIO_write(bp, (const char *)p, (int)len) !=
211
				    (int)len)
212
					goto end;
213
			} else if (tag == V_ASN1_OBJECT) {
214
				opp = op;
215
				if (d2i_ASN1_OBJECT(&o, &opp, len + hl) !=
216
				    NULL) {
217
					if (BIO_write(bp, ":", 1) <= 0)
218
						goto end;
219
					i2a_ASN1_OBJECT(bp, o);
220
				} else {
221
					if (BIO_write(bp, ":BAD OBJECT",
222
					    11) <= 0)
223
						goto end;
224
				}
225
			} else if (tag == V_ASN1_BOOLEAN) {
226
				int ii;
227
228
				opp = op;
229
				ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
230
				if (ii < 0) {
231
					if (BIO_write(bp, "Bad boolean\n",
232
					    12) <= 0)
233
						goto end;
234
				}
235
				BIO_printf(bp, ":%d", ii);
236
			} else if (tag == V_ASN1_BMPSTRING) {
237
				/* do the BMP thang */
238
			} else if (tag == V_ASN1_OCTET_STRING) {
239
				int i, printable = 1;
240
241
				opp = op;
242
				os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
243
				if (os != NULL && os->length > 0) {
244
					opp = os->data;
245
					/* testing whether the octet string is
246
					 * printable */
247
					for (i = 0; i < os->length; i++) {
248
						if (((opp[i] < ' ') &&
249
						    (opp[i] != '\n') &&
250
						    (opp[i] != '\r') &&
251
						    (opp[i] != '\t')) ||
252
						    (opp[i] > '~')) {
253
							printable = 0;
254
							break;
255
						}
256
					}
257
					if (printable) {
258
						/* printable string */
259
						if (BIO_write(bp, ":", 1) <= 0)
260
							goto end;
261
						if (BIO_write(bp, (const char *)opp,
262
							    os->length) <= 0)
263
							goto end;
264
					} else if (!dump) {
265
						/* not printable => print octet string
266
						 * as hex dump */
267
						if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
268
							goto end;
269
						for (i = 0; i < os->length; i++) {
270
							if (BIO_printf(bp,
271
							    "%02X", opp[i]) <= 0)
272
								goto end;
273
						}
274
					} else {
275
						/* print the normal dump */
276
						if (!nl) {
277
							if (BIO_write(bp, "\n", 1) <= 0)
278
								goto end;
279
						}
280
						if (BIO_dump_indent(bp,
281
						    (const char *)opp,
282
						    ((dump == -1 || dump >
283
						    os->length) ? os->length : dump),
284
						    dump_indent) <= 0)
285
							goto end;
286
						nl = 1;
287
					}
288
				}
289
				ASN1_OCTET_STRING_free(os);
290
				os = NULL;
291
			} else if (tag == V_ASN1_INTEGER) {
292
				ASN1_INTEGER *bs;
293
				int i;
294
295
				opp = op;
296
				bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
297
				if (bs != NULL) {
298
					if (BIO_write(bp, ":", 1) <= 0)
299
						goto end;
300
					if (bs->type == V_ASN1_NEG_INTEGER)
301
						if (BIO_write(bp, "-", 1) <= 0)
302
							goto end;
303
					for (i = 0; i < bs->length; i++) {
304
						if (BIO_printf(bp, "%02X",
305
						    bs->data[i]) <= 0)
306
							goto end;
307
					}
308
					if (bs->length == 0) {
309
						if (BIO_write(bp, "00", 2) <= 0)
310
							goto end;
311
					}
312
				} else {
313
					if (BIO_write(bp, "BAD INTEGER", 11) <= 0)
314
						goto end;
315
				}
316
				ASN1_INTEGER_free(bs);
317
			} else if (tag == V_ASN1_ENUMERATED) {
318
				ASN1_ENUMERATED *bs;
319
				int i;
320
321
				opp = op;
322
				bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
323
				if (bs != NULL) {
324
					if (BIO_write(bp, ":", 1) <= 0)
325
						goto end;
326
					if (bs->type == V_ASN1_NEG_ENUMERATED)
327
						if (BIO_write(bp, "-", 1) <= 0)
328
							goto end;
329
					for (i = 0; i < bs->length; i++) {
330
						if (BIO_printf(bp, "%02X",
331
						    bs->data[i]) <= 0)
332
							goto end;
333
					}
334
					if (bs->length == 0) {
335
						if (BIO_write(bp, "00", 2) <= 0)
336
							goto end;
337
					}
338
				} else {
339
					if (BIO_write(bp, "BAD ENUMERATED", 14) <= 0)
340
						goto end;
341
				}
342
				ASN1_ENUMERATED_free(bs);
343
			} else if (len > 0 && dump) {
344
				if (!nl) {
345
					if (BIO_write(bp, "\n", 1) <= 0)
346
						goto end;
347
				}
348
				if (BIO_dump_indent(bp, (const char *)p,
349
				    ((dump == -1 || dump > len) ? len : dump),
350
				    dump_indent) <= 0)
351
					goto end;
352
				nl = 1;
353
			}
354
355
			if (!nl) {
356
				if (BIO_write(bp, "\n", 1) <= 0)
357
					goto end;
358
			}
359
			p += len;
360
			if ((tag == V_ASN1_EOC) && (xclass == 0)) {
361
				ret = 2; /* End of sequence */
362
				goto end;
363
			}
364
		}
365
2
		length -= len;
366
	}
367
2
	ret = 1;
368
369
end:
370
2
	if (o != NULL)
371
		ASN1_OBJECT_free(o);
372
2
	ASN1_OCTET_STRING_free(os);
373
2
	*pp = p;
374
2
	return (ret);
375
2
}
376
377
const char *
378
ASN1_tag2str(int tag)
379
{
380
	static const char * const tag2str[] = {
381
		"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
382
		"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
383
		"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", 	    /* 10-13 */
384
		"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", 		    /* 15-17 */
385
		"NUMERICSTRING", "PRINTABLESTRING", "T61STRING",	    /* 18-20 */
386
		"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 */
387
		"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",	    /* 25-27 */
388
		"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"		    /* 28-30 */
389
	};
390
391
	if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
392
		tag &= ~0x100;
393
394
	if (tag < 0 || tag > 30)
395
		return "(unknown)";
396
	return tag2str[tag];
397
}