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