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