1 /* $OpenBSD: tasn_prn.c,v 1.21 2020/03/24 10:46:38 inoguchi 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(const 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(const 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(const 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(const 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(const 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 ((it->itype != ASN1_ITYPE_PRIMITIVE ||
220 	    it->utype != V_ASN1_BOOLEAN) && *fld == NULL) {
221 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
222 			if (!nohdr &&
223 			    !asn1_print_fsname(out, indent, fname, sname, pctx))
224 				return 0;
225 			if (BIO_puts(out, "<ABSENT>\n") <= 0)
226 				return 0;
227 		}
228 		return 1;
229 	}
230 
231 	switch (it->itype) {
232 	case ASN1_ITYPE_PRIMITIVE:
233 		if (it->templates) {
234 			if (!asn1_template_print_ctx(out, fld, indent,
235 			    it->templates, pctx))
236 				return 0;
237 		}
238 		/* fall thru */
239 	case ASN1_ITYPE_MSTRING:
240 		if (!asn1_primitive_print(out, fld, it,
241 		    indent, fname, sname, pctx))
242 			return 0;
243 		break;
244 
245 	case ASN1_ITYPE_EXTERN:
246 		if (!nohdr &&
247 		    !asn1_print_fsname(out, indent, fname, sname, pctx))
248 			return 0;
249 		/* Use new style print routine if possible */
250 		ef = it->funcs;
251 		if (ef && ef->asn1_ex_print) {
252 			i = ef->asn1_ex_print(out, fld, indent, "", pctx);
253 			if (!i)
254 				return 0;
255 			if ((i == 2) && (BIO_puts(out, "\n") <= 0))
256 				return 0;
257 			return 1;
258 		} else if (sname &&
259 		    BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
260 			return 0;
261 		break;
262 
263 	case ASN1_ITYPE_CHOICE:
264 		/* CHOICE type, get selector */
265 		i = asn1_get_choice_selector(fld, it);
266 		/* This should never happen... */
267 		if ((i < 0) || (i >= it->tcount)) {
268 			if (BIO_printf(out,
269 			    "ERROR: selector [%d] invalid\n", i) <= 0)
270 				return 0;
271 			return 1;
272 		}
273 		tt = it->templates + i;
274 		tmpfld = asn1_get_field_ptr(fld, tt);
275 		if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
276 			return 0;
277 		break;
278 
279 	case ASN1_ITYPE_SEQUENCE:
280 	case ASN1_ITYPE_NDEF_SEQUENCE:
281 		if (!nohdr &&
282 		    !asn1_print_fsname(out, indent, fname, sname, pctx))
283 			return 0;
284 		if (fname || sname) {
285 			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
286 				if (BIO_puts(out, " {\n") <= 0)
287 					return 0;
288 			} else {
289 				if (BIO_puts(out, "\n") <= 0)
290 					return 0;
291 			}
292 		}
293 
294 		if (asn1_cb) {
295 			i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
296 			if (i == 0)
297 				return 0;
298 			if (i == 2)
299 				return 1;
300 		}
301 
302 		/* Print each field entry */
303 		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
304 			const ASN1_TEMPLATE *seqtt;
305 
306 			seqtt = asn1_do_adb(fld, tt, 1);
307 			if (seqtt == NULL)
308 				return 0;
309 			tmpfld = asn1_get_field_ptr(fld, seqtt);
310 			if (!asn1_template_print_ctx(out, tmpfld, indent + 2,
311 			    seqtt, pctx))
312 				return 0;
313 		}
314 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
315 			if (BIO_printf(out, "%*s}\n", indent, "") < 0)
316 				return 0;
317 		}
318 
319 		if (asn1_cb) {
320 			i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
321 			if (i == 0)
322 				return 0;
323 		}
324 		break;
325 
326 	default:
327 		BIO_printf(out, "Unprocessed type %d\n", it->itype);
328 		return 0;
329 	}
330 
331 	return 1;
332 }
333 
334 int
335 asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
336     const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
337 {
338 	int i, flags;
339 	const char *sname, *fname;
340 
341 	flags = tt->flags;
342 	if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
343 		sname = tt->item->sname;
344 	else
345 		sname = NULL;
346 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
347 		fname = NULL;
348 	else
349 		fname = tt->field_name;
350 	if (flags & ASN1_TFLG_SK_MASK) {
351 		char *tname;
352 		ASN1_VALUE *skitem;
353 		STACK_OF(ASN1_VALUE) *stack;
354 
355 		/* SET OF, SEQUENCE OF */
356 		if (fname) {
357 			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
358 				if (flags & ASN1_TFLG_SET_OF)
359 					tname = "SET";
360 				else
361 					tname = "SEQUENCE";
362 				if (BIO_printf(out, "%*s%s OF %s {\n",
363 				    indent, "", tname, tt->field_name) <= 0)
364 					return 0;
365 			} else if (BIO_printf(out, "%*s%s:\n", indent, "",
366 			    fname) <= 0)
367 				return 0;
368 		}
369 		stack = (STACK_OF(ASN1_VALUE) *)*fld;
370 		for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
371 			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
372 				return 0;
373 			skitem = sk_ASN1_VALUE_value(stack, i);
374 			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
375 			    tt->item, NULL, NULL, 1, pctx))
376 				return 0;
377 		}
378 		if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
379 			return 0;
380 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
381 			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
382 				return 0;
383 		}
384 		return 1;
385 	}
386 	return asn1_item_print_ctx(out, fld, indent, tt->item,
387 	    fname, sname, 0, pctx);
388 }
389 
390 static int
391 asn1_print_fsname(BIO *out, int indent, const char *fname, const char *sname,
392     const ASN1_PCTX *pctx)
393 {
394 	static char spaces[] = "                    ";
395 	const int nspaces = sizeof(spaces) - 1;
396 
397 	while (indent > nspaces) {
398 		if (BIO_write(out, spaces, nspaces) != nspaces)
399 			return 0;
400 		indent -= nspaces;
401 	}
402 	if (BIO_write(out, spaces, indent) != indent)
403 		return 0;
404 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
405 		sname = NULL;
406 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
407 		fname = NULL;
408 	if (!sname && !fname)
409 		return 1;
410 	if (fname) {
411 		if (BIO_puts(out, fname) <= 0)
412 			return 0;
413 	}
414 	if (sname) {
415 		if (fname) {
416 			if (BIO_printf(out, " (%s)", sname) <= 0)
417 				return 0;
418 		} else {
419 			if (BIO_puts(out, sname) <= 0)
420 				return 0;
421 		}
422 	}
423 	if (BIO_write(out, ": ", 2) != 2)
424 		return 0;
425 	return 1;
426 }
427 
428 static int
429 asn1_print_boolean_ctx(BIO *out, int boolval, const ASN1_PCTX *pctx)
430 {
431 	const char *str;
432 	switch (boolval) {
433 	case -1:
434 		str = "BOOL ABSENT";
435 		break;
436 
437 	case 0:
438 		str = "FALSE";
439 		break;
440 
441 	default:
442 		str = "TRUE";
443 		break;
444 
445 	}
446 
447 	if (BIO_puts(out, str) <= 0)
448 		return 0;
449 	return 1;
450 
451 }
452 
453 static int
454 asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, const ASN1_PCTX *pctx)
455 {
456 	char *s;
457 	int ret = 1;
458 	if ((s = i2s_ASN1_INTEGER(NULL, str)) == NULL)
459 		return 0;
460 	if (BIO_puts(out, s) <= 0)
461 		ret = 0;
462 	free(s);
463 	return ret;
464 }
465 
466 static int
467 asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid, const ASN1_PCTX *pctx)
468 {
469 	char objbuf[80];
470 	const char *ln;
471 	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
472 	if (!ln)
473 		ln = "";
474 	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
475 	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
476 		return 0;
477 	return 1;
478 }
479 
480 static int
481 asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
482     const ASN1_PCTX *pctx)
483 {
484 	if (str->type == V_ASN1_BIT_STRING) {
485 		if (BIO_printf(out, " (%ld unused bits)\n",
486 		    str->flags & 0x7) <= 0)
487 			return 0;
488 	} else if (BIO_puts(out, "\n") <= 0)
489 		return 0;
490 	if ((str->length > 0) &&
491 	    BIO_dump_indent(out, (char *)str->data, str->length,
492 	    indent + 2) <= 0)
493 		return 0;
494 	return 1;
495 }
496 
497 static int
498 asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it,
499     int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx)
500 {
501 	long utype;
502 	ASN1_STRING *str;
503 	int ret = 1, needlf = 1;
504 	const char *pname;
505 
506 	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
507 		return 0;
508 
509 	if (it != NULL && it->funcs != NULL) {
510 		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
511 
512 		if (pf->prim_print == NULL)
513 			return 0;
514 
515 		return pf->prim_print(out, fld, it, indent, pctx);
516 	}
517 	if (it->itype == ASN1_ITYPE_MSTRING) {
518 		str = (ASN1_STRING *)*fld;
519 		utype = str->type & ~V_ASN1_NEG;
520 	} else {
521 		utype = it->utype;
522 		if (utype == V_ASN1_BOOLEAN)
523 			str = NULL;
524 		else
525 			str = (ASN1_STRING *)*fld;
526 	}
527 	if (utype == V_ASN1_ANY) {
528 		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
529 		utype = atype->type;
530 		fld = &atype->value.asn1_value;
531 		str = (ASN1_STRING *)*fld;
532 		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
533 			pname = NULL;
534 		else
535 			pname = ASN1_tag2str(utype);
536 	} else {
537 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
538 			pname = ASN1_tag2str(utype);
539 		else
540 			pname = NULL;
541 	}
542 
543 	if (utype == V_ASN1_NULL) {
544 		if (BIO_puts(out, "NULL\n") <= 0)
545 			return 0;
546 		return 1;
547 	}
548 
549 	if (pname) {
550 		if (BIO_puts(out, pname) <= 0)
551 			return 0;
552 		if (BIO_puts(out, ":") <= 0)
553 			return 0;
554 	}
555 
556 	switch (utype) {
557 	case V_ASN1_BOOLEAN:
558 		{
559 			int boolval = *(int *)fld;
560 			if (boolval == -1)
561 				boolval = it->size;
562 			ret = asn1_print_boolean_ctx(out, boolval, pctx);
563 		}
564 		break;
565 
566 	case V_ASN1_INTEGER:
567 	case V_ASN1_ENUMERATED:
568 		ret = asn1_print_integer_ctx(out, str, pctx);
569 		break;
570 
571 	case V_ASN1_UTCTIME:
572 		ret = ASN1_UTCTIME_print(out, str);
573 		break;
574 
575 	case V_ASN1_GENERALIZEDTIME:
576 		ret = ASN1_GENERALIZEDTIME_print(out, str);
577 		break;
578 
579 	case V_ASN1_OBJECT:
580 		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
581 		break;
582 
583 	case V_ASN1_OCTET_STRING:
584 	case V_ASN1_BIT_STRING:
585 		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
586 		needlf = 0;
587 		break;
588 
589 	case V_ASN1_SEQUENCE:
590 	case V_ASN1_SET:
591 	case V_ASN1_OTHER:
592 		if (BIO_puts(out, "\n") <= 0)
593 			return 0;
594 		if (ASN1_parse_dump(out, str->data, str->length,
595 		    indent, 0) <= 0)
596 			ret = 0;
597 		needlf = 0;
598 		break;
599 
600 	default:
601 		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
602 	}
603 	if (!ret)
604 		return 0;
605 	if (needlf && BIO_puts(out, "\n") <= 0)
606 		return 0;
607 	return 1;
608 }
609