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