GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/asn1/tasn_prn.c Lines: 0 249 0.0 %
Date: 2017-11-07 Branches: 0 218 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: tasn_prn.c,v 1.16 2017/01/29 17:49:22 beck Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2000.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2000,2005 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <stddef.h>
60
61
#include <openssl/asn1.h>
62
#include <openssl/asn1t.h>
63
#include <openssl/buffer.h>
64
#include <openssl/err.h>
65
#include <openssl/objects.h>
66
#include <openssl/x509v3.h>
67
68
#include "asn1_locl.h"
69
70
/* Print routines.
71
 */
72
73
/* ASN1_PCTX routines */
74
75
ASN1_PCTX default_pctx = {
76
	ASN1_PCTX_FLAGS_SHOW_ABSENT,	/* flags */
77
	0,				/* nm_flags */
78
	0,				/* cert_flags */
79
	0,				/* oid_flags */
80
	0				/* str_flags */
81
};
82
83
84
ASN1_PCTX *
85
ASN1_PCTX_new(void)
86
{
87
	ASN1_PCTX *ret;
88
	ret = malloc(sizeof(ASN1_PCTX));
89
	if (ret == NULL) {
90
		ASN1error(ERR_R_MALLOC_FAILURE);
91
		return NULL;
92
	}
93
	ret->flags = 0;
94
	ret->nm_flags = 0;
95
	ret->cert_flags = 0;
96
	ret->oid_flags = 0;
97
	ret->str_flags = 0;
98
	return ret;
99
}
100
101
void
102
ASN1_PCTX_free(ASN1_PCTX *p)
103
{
104
	free(p);
105
}
106
107
unsigned long
108
ASN1_PCTX_get_flags(ASN1_PCTX *p)
109
{
110
	return p->flags;
111
}
112
113
void
114
ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
115
{
116
	p->flags = flags;
117
}
118
119
unsigned long
120
ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
121
{
122
	return p->nm_flags;
123
}
124
125
void
126
ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
127
{
128
	p->nm_flags = flags;
129
}
130
131
unsigned long
132
ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
133
{
134
	return p->cert_flags;
135
}
136
137
void
138
ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
139
{
140
	p->cert_flags = flags;
141
}
142
143
unsigned long
144
ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
145
{
146
	return p->oid_flags;
147
}
148
149
void
150
ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
151
{
152
	p->oid_flags = flags;
153
}
154
155
unsigned long
156
ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
157
{
158
	return p->str_flags;
159
}
160
161
void
162
ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
163
{
164
	p->str_flags = flags;
165
}
166
167
/* Main print routines */
168
169
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
170
    const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr,
171
    const ASN1_PCTX *pctx);
172
173
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
174
    const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
175
176
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
177
    const ASN1_ITEM *it, int indent, const char *fname, const char *sname,
178
    const ASN1_PCTX *pctx);
179
180
static int asn1_print_fsname(BIO *out, int indent, const char *fname,
181
    const char *sname, const ASN1_PCTX *pctx);
182
183
int
184
ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it,
185
    const ASN1_PCTX *pctx)
186
{
187
	const char *sname;
188
189
	if (pctx == NULL)
190
		pctx = &default_pctx;
191
	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
192
		sname = NULL;
193
	else
194
		sname = it->sname;
195
	return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname,
196
	    0, pctx);
197
}
198
199
static int
200
asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, const ASN1_ITEM *it,
201
    const char *fname, const char *sname, int nohdr, const ASN1_PCTX *pctx)
202
{
203
	const ASN1_TEMPLATE *tt;
204
	const ASN1_EXTERN_FUNCS *ef;
205
	ASN1_VALUE **tmpfld;
206
	const ASN1_AUX *aux = it->funcs;
207
	ASN1_aux_cb *asn1_cb;
208
	ASN1_PRINT_ARG parg;
209
	int i;
210
211
	if (aux && aux->asn1_cb) {
212
		parg.out = out;
213
		parg.indent = indent;
214
		parg.pctx = pctx;
215
		asn1_cb = aux->asn1_cb;
216
	} else
217
		asn1_cb = NULL;
218
219
	if (*fld == NULL) {
220
		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
221
			if (!nohdr &&
222
			    !asn1_print_fsname(out, indent, fname, sname, pctx))
223
				return 0;
224
			if (BIO_puts(out, "<ABSENT>\n") <= 0)
225
				return 0;
226
		}
227
		return 1;
228
	}
229
230
	switch (it->itype) {
231
	case ASN1_ITYPE_PRIMITIVE:
232
		if (it->templates) {
233
			if (!asn1_template_print_ctx(out, fld, indent,
234
			    it->templates, pctx))
235
				return 0;
236
		}
237
		/* fall thru */
238
	case ASN1_ITYPE_MSTRING:
239
		if (!asn1_primitive_print(out, fld, it,
240
		    indent, fname, sname, pctx))
241
			return 0;
242
		break;
243
244
	case ASN1_ITYPE_EXTERN:
245
		if (!nohdr &&
246
		    !asn1_print_fsname(out, indent, fname, sname, pctx))
247
			return 0;
248
		/* Use new style print routine if possible */
249
		ef = it->funcs;
250
		if (ef && ef->asn1_ex_print) {
251
			i = ef->asn1_ex_print(out, fld, indent, "", pctx);
252
			if (!i)
253
				return 0;
254
			if ((i == 2) && (BIO_puts(out, "\n") <= 0))
255
				return 0;
256
			return 1;
257
		} else if (sname &&
258
		    BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
259
			return 0;
260
		break;
261
262
	case ASN1_ITYPE_CHOICE:
263
		/* CHOICE type, get selector */
264
		i = asn1_get_choice_selector(fld, it);
265
		/* This should never happen... */
266
		if ((i < 0) || (i >= it->tcount)) {
267
			if (BIO_printf(out,
268
			    "ERROR: selector [%d] invalid\n", i) <= 0)
269
				return 0;
270
			return 1;
271
		}
272
		tt = it->templates + i;
273
		tmpfld = asn1_get_field_ptr(fld, tt);
274
		if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
275
			return 0;
276
		break;
277
278
	case ASN1_ITYPE_SEQUENCE:
279
	case ASN1_ITYPE_NDEF_SEQUENCE:
280
		if (!nohdr &&
281
		    !asn1_print_fsname(out, indent, fname, sname, pctx))
282
			return 0;
283
		if (fname || sname) {
284
			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
285
				if (BIO_puts(out, " {\n") <= 0)
286
					return 0;
287
			} else {
288
				if (BIO_puts(out, "\n") <= 0)
289
					return 0;
290
			}
291
		}
292
293
		if (asn1_cb) {
294
			i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
295
			if (i == 0)
296
				return 0;
297
			if (i == 2)
298
				return 1;
299
		}
300
301
		/* Print each field entry */
302
		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
303
			const ASN1_TEMPLATE *seqtt;
304
305
			seqtt = asn1_do_adb(fld, tt, 1);
306
			if (seqtt == NULL)
307
				return 0;
308
			tmpfld = asn1_get_field_ptr(fld, seqtt);
309
			if (!asn1_template_print_ctx(out, tmpfld, indent + 2,
310
			    seqtt, pctx))
311
				return 0;
312
		}
313
		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
314
			if (BIO_printf(out, "%*s}\n", indent, "") < 0)
315
				return 0;
316
		}
317
318
		if (asn1_cb) {
319
			i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
320
			if (i == 0)
321
				return 0;
322
		}
323
		break;
324
325
	default:
326
		BIO_printf(out, "Unprocessed type %d\n", it->itype);
327
		return 0;
328
	}
329
330
	return 1;
331
}
332
333
int
334
asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
335
    const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
336
{
337
	int i, flags;
338
	const char *sname, *fname;
339
340
	flags = tt->flags;
341
	if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
342
		sname = tt->item->sname;
343
	else
344
		sname = NULL;
345
	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
346
		fname = NULL;
347
	else
348
		fname = tt->field_name;
349
	if (flags & ASN1_TFLG_SK_MASK) {
350
		char *tname;
351
		ASN1_VALUE *skitem;
352
		STACK_OF(ASN1_VALUE) *stack;
353
354
		/* SET OF, SEQUENCE OF */
355
		if (fname) {
356
			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
357
				if (flags & ASN1_TFLG_SET_OF)
358
					tname = "SET";
359
				else
360
					tname = "SEQUENCE";
361
				if (BIO_printf(out, "%*s%s OF %s {\n",
362
				    indent, "", tname, tt->field_name) <= 0)
363
					return 0;
364
			} else if (BIO_printf(out, "%*s%s:\n", indent, "",
365
			    fname) <= 0)
366
				return 0;
367
		}
368
		stack = (STACK_OF(ASN1_VALUE) *)*fld;
369
		for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
370
			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
371
				return 0;
372
			skitem = sk_ASN1_VALUE_value(stack, i);
373
			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
374
			    tt->item, NULL, NULL, 1, pctx))
375
				return 0;
376
		}
377
		if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
378
			return 0;
379
		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
380
			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
381
				return 0;
382
		}
383
		return 1;
384
	}
385
	return asn1_item_print_ctx(out, fld, indent, tt->item,
386
	    fname, sname, 0, pctx);
387
}
388
389
static int
390
asn1_print_fsname(BIO *out, int indent, const char *fname, const char *sname,
391
    const ASN1_PCTX *pctx)
392
{
393
	static char spaces[] = "                    ";
394
	const int nspaces = sizeof(spaces) - 1;
395
396
	while (indent > nspaces) {
397
		if (BIO_write(out, spaces, nspaces) != nspaces)
398
			return 0;
399
		indent -= nspaces;
400
	}
401
	if (BIO_write(out, spaces, indent) != indent)
402
		return 0;
403
	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
404
		sname = NULL;
405
	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
406
		fname = NULL;
407
	if (!sname && !fname)
408
		return 1;
409
	if (fname) {
410
		if (BIO_puts(out, fname) <= 0)
411
			return 0;
412
	}
413
	if (sname) {
414
		if (fname) {
415
			if (BIO_printf(out, " (%s)", sname) <= 0)
416
				return 0;
417
		} else {
418
			if (BIO_puts(out, sname) <= 0)
419
				return 0;
420
		}
421
	}
422
	if (BIO_write(out, ": ", 2) != 2)
423
		return 0;
424
	return 1;
425
}
426
427
static int
428
asn1_print_boolean_ctx(BIO *out, int boolval, const ASN1_PCTX *pctx)
429
{
430
	const char *str;
431
	switch (boolval) {
432
	case -1:
433
		str = "BOOL ABSENT";
434
		break;
435
436
	case 0:
437
		str = "FALSE";
438
		break;
439
440
	default:
441
		str = "TRUE";
442
		break;
443
444
	}
445
446
	if (BIO_puts(out, str) <= 0)
447
		return 0;
448
	return 1;
449
450
}
451
452
static int
453
asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, const ASN1_PCTX *pctx)
454
{
455
	char *s;
456
	int ret = 1;
457
	s = i2s_ASN1_INTEGER(NULL, str);
458
	if (BIO_puts(out, s) <= 0)
459
		ret = 0;
460
	free(s);
461
	return ret;
462
}
463
464
static int
465
asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid, const ASN1_PCTX *pctx)
466
{
467
	char objbuf[80];
468
	const char *ln;
469
	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
470
	if (!ln)
471
		ln = "";
472
	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
473
	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
474
		return 0;
475
	return 1;
476
}
477
478
static int
479
asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
480
    const ASN1_PCTX *pctx)
481
{
482
	if (str->type == V_ASN1_BIT_STRING) {
483
		if (BIO_printf(out, " (%ld unused bits)\n",
484
		    str->flags & 0x7) <= 0)
485
			return 0;
486
	} else if (BIO_puts(out, "\n") <= 0)
487
		return 0;
488
	if ((str->length > 0) &&
489
	    BIO_dump_indent(out, (char *)str->data, str->length,
490
	    indent + 2) <= 0)
491
		return 0;
492
	return 1;
493
}
494
495
static int
496
asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it,
497
    int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx)
498
{
499
	long utype;
500
	ASN1_STRING *str;
501
	int ret = 1, needlf = 1;
502
	const char *pname;
503
	const ASN1_PRIMITIVE_FUNCS *pf;
504
505
	pf = it->funcs;
506
	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
507
		return 0;
508
	if (pf && pf->prim_print)
509
		return pf->prim_print(out, fld, it, indent, pctx);
510
	str = (ASN1_STRING *)*fld;
511
	if (it->itype == ASN1_ITYPE_MSTRING)
512
		utype = str->type & ~V_ASN1_NEG;
513
	else
514
		utype = it->utype;
515
	if (utype == V_ASN1_ANY) {
516
		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
517
		utype = atype->type;
518
		fld = &atype->value.asn1_value;
519
		str = (ASN1_STRING *)*fld;
520
		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
521
			pname = NULL;
522
		else
523
			pname = ASN1_tag2str(utype);
524
	} else {
525
		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
526
			pname = ASN1_tag2str(utype);
527
		else
528
			pname = NULL;
529
	}
530
531
	if (utype == V_ASN1_NULL) {
532
		if (BIO_puts(out, "NULL\n") <= 0)
533
			return 0;
534
		return 1;
535
	}
536
537
	if (pname) {
538
		if (BIO_puts(out, pname) <= 0)
539
			return 0;
540
		if (BIO_puts(out, ":") <= 0)
541
			return 0;
542
	}
543
544
	switch (utype) {
545
	case V_ASN1_BOOLEAN:
546
		{
547
			int boolval = *(int *)fld;
548
			if (boolval == -1)
549
				boolval = it->size;
550
			ret = asn1_print_boolean_ctx(out, boolval, pctx);
551
		}
552
		break;
553
554
	case V_ASN1_INTEGER:
555
	case V_ASN1_ENUMERATED:
556
		ret = asn1_print_integer_ctx(out, str, pctx);
557
		break;
558
559
	case V_ASN1_UTCTIME:
560
		ret = ASN1_UTCTIME_print(out, str);
561
		break;
562
563
	case V_ASN1_GENERALIZEDTIME:
564
		ret = ASN1_GENERALIZEDTIME_print(out, str);
565
		break;
566
567
	case V_ASN1_OBJECT:
568
		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
569
		break;
570
571
	case V_ASN1_OCTET_STRING:
572
	case V_ASN1_BIT_STRING:
573
		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
574
		needlf = 0;
575
		break;
576
577
	case V_ASN1_SEQUENCE:
578
	case V_ASN1_SET:
579
	case V_ASN1_OTHER:
580
		if (BIO_puts(out, "\n") <= 0)
581
			return 0;
582
		if (ASN1_parse_dump(out, str->data, str->length,
583
		    indent, 0) <= 0)
584
			ret = 0;
585
		needlf = 0;
586
		break;
587
588
	default:
589
		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
590
	}
591
	if (!ret)
592
		return 0;
593
	if (needlf && BIO_puts(out, "\n") <= 0)
594
		return 0;
595
	return 1;
596
}