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 * 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 98 ASN1_PCTX_free(ASN1_PCTX *p) 99 { 100 free(p); 101 } 102 103 unsigned long 104 ASN1_PCTX_get_flags(const ASN1_PCTX *p) 105 { 106 return p->flags; 107 } 108 109 void 110 ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags) 111 { 112 p->flags = flags; 113 } 114 115 unsigned long 116 ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p) 117 { 118 return p->nm_flags; 119 } 120 121 void 122 ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags) 123 { 124 p->nm_flags = flags; 125 } 126 127 unsigned long 128 ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p) 129 { 130 return p->cert_flags; 131 } 132 133 void 134 ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags) 135 { 136 p->cert_flags = flags; 137 } 138 139 unsigned long 140 ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p) 141 { 142 return p->oid_flags; 143 } 144 145 void 146 ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags) 147 { 148 p->oid_flags = flags; 149 } 150 151 unsigned long 152 ASN1_PCTX_get_str_flags(const ASN1_PCTX *p) 153 { 154 return p->str_flags; 155 } 156 157 void 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 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 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 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 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 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 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 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 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 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