Home | History | Annotate | Download | only in asn1
      1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      2  * All rights reserved.
      3  *
      4  * This package is an SSL implementation written
      5  * by Eric Young (eay (at) cryptsoft.com).
      6  * The implementation was written so as to conform with Netscapes SSL.
      7  *
      8  * This library is free for commercial and non-commercial use as long as
      9  * the following conditions are aheared to.  The following conditions
     10  * apply to all code found in this distribution, be it the RC4, RSA,
     11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     12  * included with this distribution is covered by the same copyright terms
     13  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     14  *
     15  * Copyright remains Eric Young's, and as such any Copyright notices in
     16  * the code are not to be removed.
     17  * If this package is used in a product, Eric Young should be given attribution
     18  * as the author of the parts of the library used.
     19  * This can be in the form of a textual message at program startup or
     20  * in documentation (online or textual) provided with the package.
     21  *
     22  * Redistribution and use in source and binary forms, with or without
     23  * modification, are permitted provided that the following conditions
     24  * are met:
     25  * 1. Redistributions of source code must retain the copyright
     26  *    notice, this list of conditions and the following disclaimer.
     27  * 2. Redistributions in binary form must reproduce the above copyright
     28  *    notice, this list of conditions and the following disclaimer in the
     29  *    documentation and/or other materials provided with the distribution.
     30  * 3. All advertising materials mentioning features or use of this software
     31  *    must display the following acknowledgement:
     32  *    "This product includes cryptographic software written by
     33  *     Eric Young (eay (at) cryptsoft.com)"
     34  *    The word 'cryptographic' can be left out if the rouines from the library
     35  *    being used are not cryptographic related :-).
     36  * 4. If you include any Windows specific code (or a derivative thereof) from
     37  *    the apps directory (application code) you must include an acknowledgement:
     38  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     50  * SUCH DAMAGE.
     51  *
     52  * The licence and distribution terms for any publically available version or
     53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     54  * copied and put under another distribution licence
     55  * [including the GNU Public Licence.] */
     56 
     57 #include <openssl/asn1.h>
     58 
     59 #include <time.h>
     60 
     61 #include <openssl/asn1t.h>
     62 #include <openssl/err.h>
     63 #include <openssl/obj.h>
     64 #include <openssl/mem.h>
     65 
     66 #include "asn1_locl.h"
     67 
     68 
     69 
     70 /* Print routines.
     71  */
     72 
     73 /* ASN1_PCTX routines */
     74 
     75 static 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 		OPENSSL_PUT_ERROR(ASN1, 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 			break;
    233 			}
    234 		/* fall thru */
    235 		case ASN1_ITYPE_MSTRING:
    236 		if (!asn1_primitive_print(out, fld, it,
    237 				indent, fname, sname,pctx))
    238 			return 0;
    239 		break;
    240 
    241 		case ASN1_ITYPE_EXTERN:
    242 		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
    243 			return 0;
    244 		/* Use new style print routine if possible */
    245 		ef = it->funcs;
    246 		if (ef && ef->asn1_ex_print)
    247 			{
    248 			i = ef->asn1_ex_print(out, fld, indent, "", pctx);
    249 			if (!i)
    250 				return 0;
    251 			if ((i == 2) && (BIO_puts(out, "\n") <= 0))
    252 				return 0;
    253 			return 1;
    254 			}
    255 		else if (sname &&
    256 			BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
    257 			return 0;
    258 		break;
    259 
    260 		case ASN1_ITYPE_CHOICE:
    261 #if 0
    262 		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
    263 			return 0;
    264 #endif
    265 		/* CHOICE type, get selector */
    266 		i = asn1_get_choice_selector(fld, it);
    267 		/* This should never happen... */
    268 		if((i < 0) || (i >= it->tcount))
    269 			{
    270 			if (BIO_printf(out,
    271 				"ERROR: selector [%d] invalid\n", i) <= 0)
    272 				return 0;
    273 			return 1;
    274 			}
    275 		tt = it->templates + i;
    276 		tmpfld = asn1_get_field_ptr(fld, tt);
    277 		if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
    278 			return 0;
    279 		break;
    280 
    281 		case ASN1_ITYPE_SEQUENCE:
    282 		case ASN1_ITYPE_NDEF_SEQUENCE:
    283 		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
    284 			return 0;
    285 		if (fname || sname)
    286 			{
    287 			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
    288 				{
    289 				if (BIO_puts(out, " {\n") <= 0)
    290 					return 0;
    291 				}
    292 			else
    293 				{
    294 				if (BIO_puts(out, "\n") <= 0)
    295 					return 0;
    296 				}
    297 			}
    298 
    299 		if (asn1_cb)
    300 			{
    301 			i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
    302 			if (i == 0)
    303 				return 0;
    304 			if (i == 2)
    305 				return 1;
    306 			}
    307 
    308 		/* Print each field entry */
    309 		for(i = 0, tt = it->templates; i < it->tcount; i++, tt++)
    310 			{
    311 			const ASN1_TEMPLATE *seqtt;
    312 			seqtt = asn1_do_adb(fld, tt, 1);
    313 			if (!seqtt)
    314 				return 0;
    315 			tmpfld = asn1_get_field_ptr(fld, seqtt);
    316 			if (!asn1_template_print_ctx(out, tmpfld,
    317 						indent + 2, seqtt, pctx))
    318 				return 0;
    319 			}
    320 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
    321 			{
    322 			if (BIO_printf(out, "%*s}\n", indent, "") < 0)
    323 				return 0;
    324 			}
    325 
    326 		if (asn1_cb)
    327 			{
    328 			i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
    329 			if (i == 0)
    330 				return 0;
    331 			}
    332 		break;
    333 
    334 		default:
    335 		BIO_printf(out, "Unprocessed type %d\n", it->itype);
    336 		return 0;
    337 		}
    338 
    339 	return 1;
    340 	}
    341 
    342 int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
    343 				const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
    344 	{
    345 	int flags;
    346 	size_t i;
    347 	const char *sname, *fname;
    348 	flags = tt->flags;
    349 	if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
    350 		sname = ASN1_ITEM_ptr(tt->item)->sname;
    351 	else
    352 		sname = NULL;
    353 	if(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
    354 		fname = NULL;
    355 	else
    356 		fname = tt->field_name;
    357 	if(flags & ASN1_TFLG_SK_MASK)
    358 		{
    359 		const char *tname;
    360 		ASN1_VALUE *skitem;
    361 		STACK_OF(ASN1_VALUE) *stack;
    362 
    363 		/* SET OF, SEQUENCE OF */
    364 		if (fname)
    365 			{
    366 			if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF)
    367 				{
    368 				if(flags & ASN1_TFLG_SET_OF)
    369 					tname = "SET";
    370 				else
    371 					tname = "SEQUENCE";
    372 				if (BIO_printf(out, "%*s%s OF %s {\n",
    373 					indent, "", tname, tt->field_name) <= 0)
    374 					return 0;
    375 				}
    376 			else if (BIO_printf(out, "%*s%s:\n", indent, "",
    377 					fname) <= 0)
    378 				return 0;
    379 			}
    380 		stack = (STACK_OF(ASN1_VALUE) *)*fld;
    381 		for(i = 0; i < sk_ASN1_VALUE_num(stack); i++)
    382 			{
    383 			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
    384 				return 0;
    385 
    386 			skitem = sk_ASN1_VALUE_value(stack, i);
    387 			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
    388 				ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
    389 				return 0;
    390 			}
    391 		if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
    392 				return 0;
    393 		if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
    394 			{
    395 			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
    396 				return 0;
    397 			}
    398 		return 1;
    399 		}
    400 	return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
    401 							fname, sname, 0, pctx);
    402 	}
    403 
    404 static int asn1_print_fsname(BIO *out, int indent,
    405 			const char *fname, const char *sname,
    406 			const ASN1_PCTX *pctx)
    407 	{
    408 	static char spaces[] = "                    ";
    409 	const int nspaces = sizeof(spaces) - 1;
    410 
    411 #if 0
    412 	if (!sname && !fname)
    413 		return 1;
    414 #endif
    415 
    416 	while (indent > nspaces)
    417 		{
    418 		if (BIO_write(out, spaces, nspaces) != nspaces)
    419 			return 0;
    420 		indent -= nspaces;
    421 		}
    422 	if (BIO_write(out, spaces, indent) != indent)
    423 		return 0;
    424 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
    425 		sname = NULL;
    426 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
    427 		fname = NULL;
    428 	if (!sname && !fname)
    429 		return 1;
    430 	if (fname)
    431 		{
    432 		if (BIO_puts(out, fname) <= 0)
    433 			return 0;
    434 		}
    435 	if (sname)
    436 		{
    437 		if (fname)
    438 			{
    439 			if (BIO_printf(out, " (%s)", sname) <= 0)
    440 				return 0;
    441 			}
    442 		else
    443 			{
    444 			if (BIO_puts(out, sname) <= 0)
    445 				return 0;
    446 			}
    447 		}
    448 	if (BIO_write(out, ": ", 2) != 2)
    449 		return 0;
    450 	return 1;
    451 	}
    452 
    453 static int asn1_print_boolean_ctx(BIO *out, int boolval,
    454 							const ASN1_PCTX *pctx)
    455 	{
    456 	const char *str;
    457 	switch (boolval)
    458 		{
    459 		case -1:
    460 		str = "BOOL ABSENT";
    461 		break;
    462 
    463 		case 0:
    464 		str = "FALSE";
    465 		break;
    466 
    467 		default:
    468 		str = "TRUE";
    469 		break;
    470 
    471 		}
    472 
    473 	if (BIO_puts(out, str) <= 0)
    474 		return 0;
    475 	return 1;
    476 
    477 	}
    478 
    479 static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
    480 						const ASN1_PCTX *pctx)
    481 	{
    482 	BIGNUM *bn = NULL;
    483 	char *s = NULL;
    484 	int ret = 1;
    485 
    486 	bn = ASN1_INTEGER_to_BN(str, NULL);
    487 	if (bn == NULL) {
    488 		return 0;
    489 	}
    490 	s = BN_bn2dec(bn);
    491 	BN_free(bn);
    492 	if (s == NULL) {
    493 		return 0;
    494 	}
    495 
    496 	if (BIO_puts(out, s) <= 0) {
    497 		ret = 0;
    498 	}
    499 	OPENSSL_free(s);
    500 	return ret;
    501 	}
    502 
    503 static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
    504 						const ASN1_PCTX *pctx)
    505 	{
    506 	char objbuf[80];
    507 	const char *ln;
    508 	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
    509 	if(!ln)
    510 		ln = "";
    511 	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
    512 	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
    513 		return 0;
    514 	return 1;
    515 	}
    516 
    517 static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
    518 						const ASN1_PCTX *pctx)
    519 	{
    520 	if (str->type == V_ASN1_BIT_STRING)
    521 		{
    522 		if (BIO_printf(out, " (%ld unused bits)\n",
    523 					str->flags & 0x7) <= 0)
    524 				return 0;
    525 		}
    526 	else if (BIO_puts(out, "\n") <= 0)
    527 		return 0;
    528 	if (str->length > 0 && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
    529 		return 0;
    530 	}
    531 	return 1;
    532 	}
    533 
    534 static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
    535 				const ASN1_ITEM *it, int indent,
    536 				const char *fname, const char *sname,
    537 				const ASN1_PCTX *pctx)
    538 	{
    539 	long utype;
    540 	ASN1_STRING *str;
    541 	int ret = 1, needlf = 1;
    542 	const char *pname;
    543 	const ASN1_PRIMITIVE_FUNCS *pf;
    544 	pf = it->funcs;
    545 	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
    546 			return 0;
    547 	if (pf && pf->prim_print)
    548 		return pf->prim_print(out, fld, it, indent, pctx);
    549 	str = (ASN1_STRING *)*fld;
    550 	if (it->itype == ASN1_ITYPE_MSTRING)
    551 		utype = str->type & ~V_ASN1_NEG;
    552 	else
    553 		utype = it->utype;
    554 	if (utype == V_ASN1_ANY)
    555 		{
    556 		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
    557 		utype = atype->type;
    558 		fld = &atype->value.asn1_value;
    559 		str = (ASN1_STRING *)*fld;
    560 		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
    561 			pname = NULL;
    562 		else
    563 			pname = ASN1_tag2str(utype);
    564 		}
    565 	else
    566 		{
    567 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
    568 			pname = ASN1_tag2str(utype);
    569 		else
    570 			pname = NULL;
    571 		}
    572 
    573 	if (utype == V_ASN1_NULL)
    574 		{
    575 		if (BIO_puts(out, "NULL\n") <= 0)
    576 			return 0;
    577 		return 1;
    578 		}
    579 
    580 	if (pname)
    581 		{
    582 		if (BIO_puts(out, pname) <= 0)
    583 			return 0;
    584 		if (BIO_puts(out, ":") <= 0)
    585 			return 0;
    586 		}
    587 
    588 	switch (utype)
    589 		{
    590 		case V_ASN1_BOOLEAN:
    591 			{
    592 			int boolval = *(int *)fld;
    593 			if (boolval == -1)
    594 				boolval = it->size;
    595 			ret = asn1_print_boolean_ctx(out, boolval, pctx);
    596 			}
    597 		break;
    598 
    599 		case V_ASN1_INTEGER:
    600 		case V_ASN1_ENUMERATED:
    601 		ret = asn1_print_integer_ctx(out, str, pctx);
    602 		break;
    603 
    604 		case V_ASN1_UTCTIME:
    605 		ret = ASN1_UTCTIME_print(out, str);
    606 		break;
    607 
    608 		case V_ASN1_GENERALIZEDTIME:
    609 		ret = ASN1_GENERALIZEDTIME_print(out, str);
    610 		break;
    611 
    612 		case V_ASN1_OBJECT:
    613 		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
    614 		break;
    615 
    616 		case V_ASN1_OCTET_STRING:
    617 		case V_ASN1_BIT_STRING:
    618 		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
    619 		needlf = 0;
    620 		break;
    621 
    622 		case V_ASN1_SEQUENCE:
    623 		case V_ASN1_SET:
    624 		case V_ASN1_OTHER:
    625 		if (BIO_puts(out, "\n") <= 0)
    626 			return 0;
    627 		if (ASN1_parse_dump(out, str->data, str->length,
    628 						indent, 0) <= 0)
    629 			ret = 0;
    630 		needlf = 0;
    631 		break;
    632 
    633 		default:
    634 		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
    635 
    636 		}
    637 	if (!ret)
    638 		return 0;
    639 	if (needlf && BIO_puts(out, "\n") <= 0)
    640 		return 0;
    641 	return 1;
    642 	}
    643