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