1/* 2 * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include <stddef.h> 11#include "internal/cryptlib.h" 12#include <openssl/asn1.h> 13#include <openssl/asn1t.h> 14#include <openssl/objects.h> 15#include <openssl/buffer.h> 16#include <openssl/err.h> 17#include <openssl/x509v3.h> 18#include "crypto/asn1.h" 19#include "asn1_local.h" 20 21/* 22 * Print routines. 23 */ 24 25/* ASN1_PCTX routines */ 26 27static ASN1_PCTX default_pctx = { 28 ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */ 29 0, /* nm_flags */ 30 0, /* cert_flags */ 31 0, /* oid_flags */ 32 0 /* str_flags */ 33}; 34 35ASN1_PCTX *ASN1_PCTX_new(void) 36{ 37 ASN1_PCTX *ret; 38 39 ret = OPENSSL_zalloc(sizeof(*ret)); 40 if (ret == NULL) { 41 ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 42 return NULL; 43 } 44 return ret; 45} 46 47void ASN1_PCTX_free(ASN1_PCTX *p) 48{ 49 OPENSSL_free(p); 50} 51 52unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p) 53{ 54 return p->flags; 55} 56 57void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags) 58{ 59 p->flags = flags; 60} 61 62unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p) 63{ 64 return p->nm_flags; 65} 66 67void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags) 68{ 69 p->nm_flags = flags; 70} 71 72unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p) 73{ 74 return p->cert_flags; 75} 76 77void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags) 78{ 79 p->cert_flags = flags; 80} 81 82unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p) 83{ 84 return p->oid_flags; 85} 86 87void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags) 88{ 89 p->oid_flags = flags; 90} 91 92unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p) 93{ 94 return p->str_flags; 95} 96 97void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags) 98{ 99 p->str_flags = flags; 100} 101 102/* Main print routines */ 103 104static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, 105 const ASN1_ITEM *it, 106 const char *fname, const char *sname, 107 int nohdr, const ASN1_PCTX *pctx); 108 109static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, 110 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx); 111 112static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, 113 const ASN1_ITEM *it, int indent, 114 const char *fname, const char *sname, 115 const ASN1_PCTX *pctx); 116 117static int asn1_print_fsname(BIO *out, int indent, 118 const char *fname, const char *sname, 119 const ASN1_PCTX *pctx); 120 121int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent, 122 const ASN1_ITEM *it, const ASN1_PCTX *pctx) 123{ 124 const char *sname; 125 if (pctx == NULL) 126 pctx = &default_pctx; 127 if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) 128 sname = NULL; 129 else 130 sname = it->sname; 131 return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx); 132} 133 134static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, 135 const ASN1_ITEM *it, 136 const char *fname, const char *sname, 137 int nohdr, const ASN1_PCTX *pctx) 138{ 139 const ASN1_TEMPLATE *tt; 140 const ASN1_EXTERN_FUNCS *ef; 141 const ASN1_VALUE **tmpfld; 142 const ASN1_AUX *aux = it->funcs; 143 ASN1_aux_const_cb *asn1_cb = NULL; 144 ASN1_PRINT_ARG parg; 145 int i; 146 if (aux != NULL) { 147 parg.out = out; 148 parg.indent = indent; 149 parg.pctx = pctx; 150 asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb 151 : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ 152 } 153 154 if (((it->itype != ASN1_ITYPE_PRIMITIVE) 155 || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) { 156 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) { 157 if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) 158 return 0; 159 if (BIO_puts(out, "<ABSENT>\n") <= 0) 160 return 0; 161 } 162 return 1; 163 } 164 165 switch (it->itype) { 166 case ASN1_ITYPE_PRIMITIVE: 167 if (it->templates) { 168 if (!asn1_template_print_ctx(out, fld, indent, 169 it->templates, pctx)) 170 return 0; 171 break; 172 } 173 /* fall through */ 174 case ASN1_ITYPE_MSTRING: 175 if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx)) 176 return 0; 177 break; 178 179 case ASN1_ITYPE_EXTERN: 180 if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) 181 return 0; 182 /* Use new style print routine if possible */ 183 ef = it->funcs; 184 if (ef && ef->asn1_ex_print) { 185 i = ef->asn1_ex_print(out, fld, indent, "", pctx); 186 if (!i) 187 return 0; 188 if ((i == 2) && (BIO_puts(out, "\n") <= 0)) 189 return 0; 190 return 1; 191 } else if (sname && 192 BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0) 193 return 0; 194 break; 195 196 case ASN1_ITYPE_CHOICE: 197 /* CHOICE type, get selector */ 198 i = ossl_asn1_get_choice_selector_const(fld, it); 199 /* This should never happen... */ 200 if ((i < 0) || (i >= it->tcount)) { 201 if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0) 202 return 0; 203 return 1; 204 } 205 tt = it->templates + i; 206 tmpfld = ossl_asn1_get_const_field_ptr(fld, tt); 207 if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx)) 208 return 0; 209 break; 210 211 case ASN1_ITYPE_SEQUENCE: 212 case ASN1_ITYPE_NDEF_SEQUENCE: 213 if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) 214 return 0; 215 if (fname || sname) { 216 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { 217 if (BIO_puts(out, " {\n") <= 0) 218 return 0; 219 } else { 220 if (BIO_puts(out, "\n") <= 0) 221 return 0; 222 } 223 } 224 225 if (asn1_cb) { 226 i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg); 227 if (i == 0) 228 return 0; 229 if (i == 2) 230 return 1; 231 } 232 233 /* Print each field entry */ 234 for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { 235 const ASN1_TEMPLATE *seqtt; 236 seqtt = ossl_asn1_do_adb(*fld, tt, 1); 237 if (!seqtt) 238 return 0; 239 tmpfld = ossl_asn1_get_const_field_ptr(fld, seqtt); 240 if (!asn1_template_print_ctx(out, tmpfld, 241 indent + 2, seqtt, pctx)) 242 return 0; 243 } 244 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { 245 if (BIO_printf(out, "%*s}\n", indent, "") < 0) 246 return 0; 247 } 248 249 if (asn1_cb) { 250 i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg); 251 if (i == 0) 252 return 0; 253 } 254 break; 255 256 default: 257 BIO_printf(out, "Unprocessed type %d\n", it->itype); 258 return 0; 259 } 260 261 return 1; 262} 263 264static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, 265 const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx) 266{ 267 int i, flags; 268 const char *sname, *fname; 269 const ASN1_VALUE *tfld; 270 flags = tt->flags; 271 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME) 272 sname = ASN1_ITEM_ptr(tt->item)->sname; 273 else 274 sname = NULL; 275 if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) 276 fname = NULL; 277 else 278 fname = tt->field_name; 279 280 /* 281 * If field is embedded then fld needs fixing so it is a pointer to 282 * a pointer to a field. 283 */ 284 if (flags & ASN1_TFLG_EMBED) { 285 tfld = (const ASN1_VALUE *)fld; 286 fld = &tfld; 287 } 288 289 if (flags & ASN1_TFLG_SK_MASK) { 290 char *tname; 291 const ASN1_VALUE *skitem; 292 STACK_OF(const_ASN1_VALUE) *stack; 293 294 /* SET OF, SEQUENCE OF */ 295 if (fname) { 296 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) { 297 if (flags & ASN1_TFLG_SET_OF) 298 tname = "SET"; 299 else 300 tname = "SEQUENCE"; 301 if (BIO_printf(out, "%*s%s OF %s {\n", 302 indent, "", tname, tt->field_name) <= 0) 303 return 0; 304 } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0) 305 return 0; 306 } 307 stack = (STACK_OF(const_ASN1_VALUE) *)*fld; 308 for (i = 0; i < sk_const_ASN1_VALUE_num(stack); i++) { 309 if ((i > 0) && (BIO_puts(out, "\n") <= 0)) 310 return 0; 311 312 skitem = sk_const_ASN1_VALUE_value(stack, i); 313 if (!asn1_item_print_ctx(out, &skitem, indent + 2, 314 ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, 315 pctx)) 316 return 0; 317 } 318 if (i == 0 && BIO_printf(out, "%*s<%s>\n", indent + 2, "", 319 stack == NULL ? "ABSENT" : "EMPTY") <= 0) 320 return 0; 321 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { 322 if (BIO_printf(out, "%*s}\n", indent, "") <= 0) 323 return 0; 324 } 325 return 1; 326 } 327 return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item), 328 fname, sname, 0, pctx); 329} 330 331static int asn1_print_fsname(BIO *out, int indent, 332 const char *fname, const char *sname, 333 const ASN1_PCTX *pctx) 334{ 335 static const char spaces[] = " "; 336 static const int nspaces = sizeof(spaces) - 1; 337 338 while (indent > nspaces) { 339 if (BIO_write(out, spaces, nspaces) != nspaces) 340 return 0; 341 indent -= nspaces; 342 } 343 if (BIO_write(out, spaces, indent) != indent) 344 return 0; 345 if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) 346 sname = NULL; 347 if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) 348 fname = NULL; 349 if (!sname && !fname) 350 return 1; 351 if (fname) { 352 if (BIO_puts(out, fname) <= 0) 353 return 0; 354 } 355 if (sname) { 356 if (fname) { 357 if (BIO_printf(out, " (%s)", sname) <= 0) 358 return 0; 359 } else { 360 if (BIO_puts(out, sname) <= 0) 361 return 0; 362 } 363 } 364 if (BIO_write(out, ": ", 2) != 2) 365 return 0; 366 return 1; 367} 368 369static int asn1_print_boolean(BIO *out, int boolval) 370{ 371 const char *str; 372 switch (boolval) { 373 case -1: 374 str = "BOOL ABSENT"; 375 break; 376 377 case 0: 378 str = "FALSE"; 379 break; 380 381 default: 382 str = "TRUE"; 383 break; 384 385 } 386 387 if (BIO_puts(out, str) <= 0) 388 return 0; 389 return 1; 390 391} 392 393static int asn1_print_integer(BIO *out, const ASN1_INTEGER *str) 394{ 395 char *s; 396 int ret = 1; 397 s = i2s_ASN1_INTEGER(NULL, str); 398 if (s == NULL) 399 return 0; 400 if (BIO_puts(out, s) <= 0) 401 ret = 0; 402 OPENSSL_free(s); 403 return ret; 404} 405 406static int asn1_print_oid(BIO *out, const ASN1_OBJECT *oid) 407{ 408 char objbuf[80]; 409 const char *ln; 410 ln = OBJ_nid2ln(OBJ_obj2nid(oid)); 411 if (!ln) 412 ln = ""; 413 OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1); 414 if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0) 415 return 0; 416 return 1; 417} 418 419static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent) 420{ 421 if (str->type == V_ASN1_BIT_STRING) { 422 if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0) 423 return 0; 424 } else if (BIO_puts(out, "\n") <= 0) 425 return 0; 426 if ((str->length > 0) 427 && BIO_dump_indent(out, (const char *)str->data, str->length, 428 indent + 2) <= 0) 429 return 0; 430 return 1; 431} 432 433static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, 434 const ASN1_ITEM *it, int indent, 435 const char *fname, const char *sname, 436 const ASN1_PCTX *pctx) 437{ 438 long utype; 439 ASN1_STRING *str; 440 int ret = 1, needlf = 1; 441 const char *pname; 442 const ASN1_PRIMITIVE_FUNCS *pf; 443 pf = it->funcs; 444 if (!asn1_print_fsname(out, indent, fname, sname, pctx)) 445 return 0; 446 if (pf && pf->prim_print) 447 return pf->prim_print(out, fld, it, indent, pctx); 448 if (it->itype == ASN1_ITYPE_MSTRING) { 449 str = (ASN1_STRING *)*fld; 450 utype = str->type & ~V_ASN1_NEG; 451 } else { 452 utype = it->utype; 453 if (utype == V_ASN1_BOOLEAN) 454 str = NULL; 455 else 456 str = (ASN1_STRING *)*fld; 457 } 458 if (utype == V_ASN1_ANY) { 459 const ASN1_TYPE *atype = (const ASN1_TYPE *)*fld; 460 utype = atype->type; 461 fld = (const ASN1_VALUE **)&atype->value.asn1_value; /* actually is const */ 462 str = (ASN1_STRING *)*fld; 463 if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) 464 pname = NULL; 465 else 466 pname = ASN1_tag2str(utype); 467 } else { 468 if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE) 469 pname = ASN1_tag2str(utype); 470 else 471 pname = NULL; 472 } 473 474 if (utype == V_ASN1_NULL) { 475 if (BIO_puts(out, "NULL\n") <= 0) 476 return 0; 477 return 1; 478 } 479 480 if (pname) { 481 if (BIO_puts(out, pname) <= 0) 482 return 0; 483 if (BIO_puts(out, ":") <= 0) 484 return 0; 485 } 486 487 switch (utype) { 488 case V_ASN1_BOOLEAN: 489 { 490 int boolval = *(int *)fld; 491 if (boolval == -1) 492 boolval = it->size; 493 ret = asn1_print_boolean(out, boolval); 494 } 495 break; 496 497 case V_ASN1_INTEGER: 498 case V_ASN1_ENUMERATED: 499 ret = asn1_print_integer(out, str); 500 break; 501 502 case V_ASN1_UTCTIME: 503 ret = ASN1_UTCTIME_print(out, str); 504 break; 505 506 case V_ASN1_GENERALIZEDTIME: 507 ret = ASN1_GENERALIZEDTIME_print(out, str); 508 break; 509 510 case V_ASN1_OBJECT: 511 ret = asn1_print_oid(out, (const ASN1_OBJECT *)*fld); 512 break; 513 514 case V_ASN1_OCTET_STRING: 515 case V_ASN1_BIT_STRING: 516 ret = asn1_print_obstring(out, str, indent); 517 needlf = 0; 518 break; 519 520 case V_ASN1_SEQUENCE: 521 case V_ASN1_SET: 522 case V_ASN1_OTHER: 523 if (BIO_puts(out, "\n") <= 0) 524 return 0; 525 if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0) 526 ret = 0; 527 needlf = 0; 528 break; 529 530 default: 531 ret = ASN1_STRING_print_ex(out, str, pctx->str_flags); 532 533 } 534 if (!ret) 535 return 0; 536 if (needlf && BIO_puts(out, "\n") <= 0) 537 return 0; 538 return 1; 539} 540