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