1 /* $OpenBSD: tasn_prn.c,v 1.22 2021/12/03 17:10:49 jsing 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 *
ASN1_PCTX_new(void)85 ASN1_PCTX_new(void)
86 {
87 ASN1_PCTX *p;
88
89 if ((p = calloc(1, sizeof(ASN1_PCTX))) == NULL) {
90 ASN1error(ERR_R_MALLOC_FAILURE);
91 return NULL;
92 }
93
94 return p;
95 }
96
97 void
ASN1_PCTX_free(ASN1_PCTX * p)98 ASN1_PCTX_free(ASN1_PCTX *p)
99 {
100 free(p);
101 }
102
103 unsigned long
ASN1_PCTX_get_flags(const ASN1_PCTX * p)104 ASN1_PCTX_get_flags(const ASN1_PCTX *p)
105 {
106 return p->flags;
107 }
108
109 void
ASN1_PCTX_set_flags(ASN1_PCTX * p,unsigned long flags)110 ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
111 {
112 p->flags = flags;
113 }
114
115 unsigned long
ASN1_PCTX_get_nm_flags(const ASN1_PCTX * p)116 ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p)
117 {
118 return p->nm_flags;
119 }
120
121 void
ASN1_PCTX_set_nm_flags(ASN1_PCTX * p,unsigned long flags)122 ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
123 {
124 p->nm_flags = flags;
125 }
126
127 unsigned long
ASN1_PCTX_get_cert_flags(const ASN1_PCTX * p)128 ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p)
129 {
130 return p->cert_flags;
131 }
132
133 void
ASN1_PCTX_set_cert_flags(ASN1_PCTX * p,unsigned long flags)134 ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
135 {
136 p->cert_flags = flags;
137 }
138
139 unsigned long
ASN1_PCTX_get_oid_flags(const ASN1_PCTX * p)140 ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p)
141 {
142 return p->oid_flags;
143 }
144
145 void
ASN1_PCTX_set_oid_flags(ASN1_PCTX * p,unsigned long flags)146 ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
147 {
148 p->oid_flags = flags;
149 }
150
151 unsigned long
ASN1_PCTX_get_str_flags(const ASN1_PCTX * p)152 ASN1_PCTX_get_str_flags(const ASN1_PCTX *p)
153 {
154 return p->str_flags;
155 }
156
157 void
ASN1_PCTX_set_str_flags(ASN1_PCTX * p,unsigned long flags)158 ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
159 {
160 p->str_flags = flags;
161 }
162
163 /* Main print routines */
164
165 static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
166 const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr,
167 const ASN1_PCTX *pctx);
168
169 int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
170 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
171
172 static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
173 const ASN1_ITEM *it, int indent, const char *fname, const char *sname,
174 const ASN1_PCTX *pctx);
175
176 static int asn1_print_fsname(BIO *out, int indent, const char *fname,
177 const char *sname, const ASN1_PCTX *pctx);
178
179 int
ASN1_item_print(BIO * out,ASN1_VALUE * ifld,int indent,const ASN1_ITEM * it,const ASN1_PCTX * pctx)180 ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it,
181 const ASN1_PCTX *pctx)
182 {
183 const char *sname;
184
185 if (pctx == NULL)
186 pctx = &default_pctx;
187 if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
188 sname = NULL;
189 else
190 sname = it->sname;
191 return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname,
192 0, pctx);
193 }
194
195 static int
asn1_item_print_ctx(BIO * out,ASN1_VALUE ** fld,int indent,const ASN1_ITEM * it,const char * fname,const char * sname,int nohdr,const ASN1_PCTX * pctx)196 asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, const ASN1_ITEM *it,
197 const char *fname, const char *sname, int nohdr, const ASN1_PCTX *pctx)
198 {
199 const ASN1_TEMPLATE *tt;
200 const ASN1_EXTERN_FUNCS *ef;
201 ASN1_VALUE **tmpfld;
202 const ASN1_AUX *aux = it->funcs;
203 ASN1_aux_cb *asn1_cb;
204 ASN1_PRINT_ARG parg;
205 int i;
206
207 if (aux && aux->asn1_cb) {
208 parg.out = out;
209 parg.indent = indent;
210 parg.pctx = pctx;
211 asn1_cb = aux->asn1_cb;
212 } else
213 asn1_cb = NULL;
214
215 if ((it->itype != ASN1_ITYPE_PRIMITIVE ||
216 it->utype != V_ASN1_BOOLEAN) && *fld == NULL) {
217 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
218 if (!nohdr &&
219 !asn1_print_fsname(out, indent, fname, sname, pctx))
220 return 0;
221 if (BIO_puts(out, "<ABSENT>\n") <= 0)
222 return 0;
223 }
224 return 1;
225 }
226
227 switch (it->itype) {
228 case ASN1_ITYPE_PRIMITIVE:
229 if (it->templates) {
230 if (!asn1_template_print_ctx(out, fld, indent,
231 it->templates, pctx))
232 return 0;
233 }
234 /* fall thru */
235 case ASN1_ITYPE_MSTRING:
236 if (!asn1_primitive_print(out, fld, it,
237 indent, fname, sname, pctx))
238 return 0;
239 break;
240
241 case ASN1_ITYPE_EXTERN:
242 if (!nohdr &&
243 !asn1_print_fsname(out, indent, fname, sname, pctx))
244 return 0;
245 /* Use new style print routine if possible */
246 ef = it->funcs;
247 if (ef && ef->asn1_ex_print) {
248 i = ef->asn1_ex_print(out, fld, indent, "", pctx);
249 if (!i)
250 return 0;
251 if ((i == 2) && (BIO_puts(out, "\n") <= 0))
252 return 0;
253 return 1;
254 } else if (sname &&
255 BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
256 return 0;
257 break;
258
259 case ASN1_ITYPE_CHOICE:
260 /* CHOICE type, get selector */
261 i = asn1_get_choice_selector(fld, it);
262 /* This should never happen... */
263 if ((i < 0) || (i >= it->tcount)) {
264 if (BIO_printf(out,
265 "ERROR: selector [%d] invalid\n", i) <= 0)
266 return 0;
267 return 1;
268 }
269 tt = it->templates + i;
270 tmpfld = asn1_get_field_ptr(fld, tt);
271 if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
272 return 0;
273 break;
274
275 case ASN1_ITYPE_SEQUENCE:
276 case ASN1_ITYPE_NDEF_SEQUENCE:
277 if (!nohdr &&
278 !asn1_print_fsname(out, indent, fname, sname, pctx))
279 return 0;
280 if (fname || sname) {
281 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
282 if (BIO_puts(out, " {\n") <= 0)
283 return 0;
284 } else {
285 if (BIO_puts(out, "\n") <= 0)
286 return 0;
287 }
288 }
289
290 if (asn1_cb) {
291 i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
292 if (i == 0)
293 return 0;
294 if (i == 2)
295 return 1;
296 }
297
298 /* Print each field entry */
299 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
300 const ASN1_TEMPLATE *seqtt;
301
302 seqtt = asn1_do_adb(fld, tt, 1);
303 if (seqtt == NULL)
304 return 0;
305 tmpfld = asn1_get_field_ptr(fld, seqtt);
306 if (!asn1_template_print_ctx(out, tmpfld, indent + 2,
307 seqtt, pctx))
308 return 0;
309 }
310 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
311 if (BIO_printf(out, "%*s}\n", indent, "") < 0)
312 return 0;
313 }
314
315 if (asn1_cb) {
316 i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
317 if (i == 0)
318 return 0;
319 }
320 break;
321
322 default:
323 BIO_printf(out, "Unprocessed type %d\n", it->itype);
324 return 0;
325 }
326
327 return 1;
328 }
329
330 int
asn1_template_print_ctx(BIO * out,ASN1_VALUE ** fld,int indent,const ASN1_TEMPLATE * tt,const ASN1_PCTX * pctx)331 asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
332 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
333 {
334 int i, flags;
335 const char *sname, *fname;
336
337 flags = tt->flags;
338 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
339 sname = tt->item->sname;
340 else
341 sname = NULL;
342 if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
343 fname = NULL;
344 else
345 fname = tt->field_name;
346 if (flags & ASN1_TFLG_SK_MASK) {
347 char *tname;
348 ASN1_VALUE *skitem;
349 STACK_OF(ASN1_VALUE) *stack;
350
351 /* SET OF, SEQUENCE OF */
352 if (fname) {
353 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
354 if (flags & ASN1_TFLG_SET_OF)
355 tname = "SET";
356 else
357 tname = "SEQUENCE";
358 if (BIO_printf(out, "%*s%s OF %s {\n",
359 indent, "", tname, tt->field_name) <= 0)
360 return 0;
361 } else if (BIO_printf(out, "%*s%s:\n", indent, "",
362 fname) <= 0)
363 return 0;
364 }
365 stack = (STACK_OF(ASN1_VALUE) *)*fld;
366 for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
367 if ((i > 0) && (BIO_puts(out, "\n") <= 0))
368 return 0;
369 skitem = sk_ASN1_VALUE_value(stack, i);
370 if (!asn1_item_print_ctx(out, &skitem, indent + 2,
371 tt->item, NULL, NULL, 1, pctx))
372 return 0;
373 }
374 if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
375 return 0;
376 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
377 if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
378 return 0;
379 }
380 return 1;
381 }
382 return asn1_item_print_ctx(out, fld, indent, tt->item,
383 fname, sname, 0, pctx);
384 }
385
386 static int
asn1_print_fsname(BIO * out,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)387 asn1_print_fsname(BIO *out, int indent, const char *fname, const char *sname,
388 const ASN1_PCTX *pctx)
389 {
390 static char spaces[] = " ";
391 const int nspaces = sizeof(spaces) - 1;
392
393 while (indent > nspaces) {
394 if (BIO_write(out, spaces, nspaces) != nspaces)
395 return 0;
396 indent -= nspaces;
397 }
398 if (BIO_write(out, spaces, indent) != indent)
399 return 0;
400 if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
401 sname = NULL;
402 if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
403 fname = NULL;
404 if (!sname && !fname)
405 return 1;
406 if (fname) {
407 if (BIO_puts(out, fname) <= 0)
408 return 0;
409 }
410 if (sname) {
411 if (fname) {
412 if (BIO_printf(out, " (%s)", sname) <= 0)
413 return 0;
414 } else {
415 if (BIO_puts(out, sname) <= 0)
416 return 0;
417 }
418 }
419 if (BIO_write(out, ": ", 2) != 2)
420 return 0;
421 return 1;
422 }
423
424 static int
asn1_print_boolean_ctx(BIO * out,int boolval,const ASN1_PCTX * pctx)425 asn1_print_boolean_ctx(BIO *out, int boolval, const ASN1_PCTX *pctx)
426 {
427 const char *str;
428 switch (boolval) {
429 case -1:
430 str = "BOOL ABSENT";
431 break;
432
433 case 0:
434 str = "FALSE";
435 break;
436
437 default:
438 str = "TRUE";
439 break;
440
441 }
442
443 if (BIO_puts(out, str) <= 0)
444 return 0;
445 return 1;
446
447 }
448
449 static int
asn1_print_integer_ctx(BIO * out,ASN1_INTEGER * str,const ASN1_PCTX * pctx)450 asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, const ASN1_PCTX *pctx)
451 {
452 char *s;
453 int ret = 1;
454 if ((s = i2s_ASN1_INTEGER(NULL, str)) == NULL)
455 return 0;
456 if (BIO_puts(out, s) <= 0)
457 ret = 0;
458 free(s);
459 return ret;
460 }
461
462 static int
asn1_print_oid_ctx(BIO * out,const ASN1_OBJECT * oid,const ASN1_PCTX * pctx)463 asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid, const ASN1_PCTX *pctx)
464 {
465 char objbuf[80];
466 const char *ln;
467 ln = OBJ_nid2ln(OBJ_obj2nid(oid));
468 if (!ln)
469 ln = "";
470 OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
471 if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
472 return 0;
473 return 1;
474 }
475
476 static int
asn1_print_obstring_ctx(BIO * out,ASN1_STRING * str,int indent,const ASN1_PCTX * pctx)477 asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
478 const ASN1_PCTX *pctx)
479 {
480 if (str->type == V_ASN1_BIT_STRING) {
481 if (BIO_printf(out, " (%ld unused bits)\n",
482 str->flags & 0x7) <= 0)
483 return 0;
484 } else if (BIO_puts(out, "\n") <= 0)
485 return 0;
486 if ((str->length > 0) &&
487 BIO_dump_indent(out, (char *)str->data, str->length,
488 indent + 2) <= 0)
489 return 0;
490 return 1;
491 }
492
493 static int
asn1_primitive_print(BIO * out,ASN1_VALUE ** fld,const ASN1_ITEM * it,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)494 asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it,
495 int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx)
496 {
497 long utype;
498 ASN1_STRING *str;
499 int ret = 1, needlf = 1;
500 const char *pname;
501
502 if (!asn1_print_fsname(out, indent, fname, sname, pctx))
503 return 0;
504
505 if (it != NULL && it->funcs != NULL) {
506 const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
507
508 if (pf->prim_print == NULL)
509 return 0;
510
511 return pf->prim_print(out, fld, it, indent, pctx);
512 }
513 if (it->itype == ASN1_ITYPE_MSTRING) {
514 str = (ASN1_STRING *)*fld;
515 utype = str->type & ~V_ASN1_NEG;
516 } else {
517 utype = it->utype;
518 if (utype == V_ASN1_BOOLEAN)
519 str = NULL;
520 else
521 str = (ASN1_STRING *)*fld;
522 }
523 if (utype == V_ASN1_ANY) {
524 ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
525 utype = atype->type;
526 fld = &atype->value.asn1_value;
527 str = (ASN1_STRING *)*fld;
528 if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
529 pname = NULL;
530 else
531 pname = ASN1_tag2str(utype);
532 } else {
533 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
534 pname = ASN1_tag2str(utype);
535 else
536 pname = NULL;
537 }
538
539 if (utype == V_ASN1_NULL) {
540 if (BIO_puts(out, "NULL\n") <= 0)
541 return 0;
542 return 1;
543 }
544
545 if (pname) {
546 if (BIO_puts(out, pname) <= 0)
547 return 0;
548 if (BIO_puts(out, ":") <= 0)
549 return 0;
550 }
551
552 switch (utype) {
553 case V_ASN1_BOOLEAN:
554 {
555 int boolval = *(int *)fld;
556 if (boolval == -1)
557 boolval = it->size;
558 ret = asn1_print_boolean_ctx(out, boolval, pctx);
559 }
560 break;
561
562 case V_ASN1_INTEGER:
563 case V_ASN1_ENUMERATED:
564 ret = asn1_print_integer_ctx(out, str, pctx);
565 break;
566
567 case V_ASN1_UTCTIME:
568 ret = ASN1_UTCTIME_print(out, str);
569 break;
570
571 case V_ASN1_GENERALIZEDTIME:
572 ret = ASN1_GENERALIZEDTIME_print(out, str);
573 break;
574
575 case V_ASN1_OBJECT:
576 ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
577 break;
578
579 case V_ASN1_OCTET_STRING:
580 case V_ASN1_BIT_STRING:
581 ret = asn1_print_obstring_ctx(out, str, indent, pctx);
582 needlf = 0;
583 break;
584
585 case V_ASN1_SEQUENCE:
586 case V_ASN1_SET:
587 case V_ASN1_OTHER:
588 if (BIO_puts(out, "\n") <= 0)
589 return 0;
590 if (ASN1_parse_dump(out, str->data, str->length,
591 indent, 0) <= 0)
592 ret = 0;
593 needlf = 0;
594 break;
595
596 default:
597 ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
598 }
599 if (!ret)
600 return 0;
601 if (needlf && BIO_puts(out, "\n") <= 0)
602 return 0;
603 return 1;
604 }
605