1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@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@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@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@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 
ASN1_PCTX_new(void)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 
ASN1_PCTX_free(ASN1_PCTX * p)102 void ASN1_PCTX_free(ASN1_PCTX *p)
103 	{
104 	OPENSSL_free(p);
105 	}
106 
ASN1_PCTX_get_flags(ASN1_PCTX * p)107 unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
108 	{
109 	return p->flags;
110 	}
111 
ASN1_PCTX_set_flags(ASN1_PCTX * p,unsigned long flags)112 void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
113 	{
114 	p->flags = flags;
115 	}
116 
ASN1_PCTX_get_nm_flags(ASN1_PCTX * p)117 unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
118 	{
119 	return p->nm_flags;
120 	}
121 
ASN1_PCTX_set_nm_flags(ASN1_PCTX * p,unsigned long flags)122 void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
123 	{
124 	p->nm_flags = flags;
125 	}
126 
ASN1_PCTX_get_cert_flags(ASN1_PCTX * p)127 unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
128 	{
129 	return p->cert_flags;
130 	}
131 
ASN1_PCTX_set_cert_flags(ASN1_PCTX * p,unsigned long flags)132 void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
133 	{
134 	p->cert_flags = flags;
135 	}
136 
ASN1_PCTX_get_oid_flags(ASN1_PCTX * p)137 unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
138 	{
139 	return p->oid_flags;
140 	}
141 
ASN1_PCTX_set_oid_flags(ASN1_PCTX * p,unsigned long flags)142 void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
143 	{
144 	p->oid_flags = flags;
145 	}
146 
ASN1_PCTX_get_str_flags(ASN1_PCTX * p)147 unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
148 	{
149 	return p->str_flags;
150 	}
151 
ASN1_PCTX_set_str_flags(ASN1_PCTX * p,unsigned long flags)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 
ASN1_item_print(BIO * out,ASN1_VALUE * ifld,int indent,const ASN1_ITEM * it,const ASN1_PCTX * pctx)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 
asn1_item_print_ctx(BIO * out,ASN1_VALUE ** fld,int indent,const ASN1_ITEM * it,const char * fname,const char * sname,int nohdr,const ASN1_PCTX * pctx)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 
asn1_template_print_ctx(BIO * out,ASN1_VALUE ** fld,int indent,const ASN1_TEMPLATE * tt,const ASN1_PCTX * pctx)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 
asn1_print_fsname(BIO * out,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)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 
asn1_print_boolean_ctx(BIO * out,int boolval,const ASN1_PCTX * pctx)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 
asn1_print_integer_ctx(BIO * out,ASN1_INTEGER * str,const ASN1_PCTX * pctx)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 
asn1_print_oid_ctx(BIO * out,const ASN1_OBJECT * oid,const ASN1_PCTX * pctx)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 
asn1_print_obstring_ctx(BIO * out,ASN1_STRING * str,int indent,const ASN1_PCTX * pctx)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 
asn1_primitive_print(BIO * out,ASN1_VALUE ** fld,const ASN1_ITEM * it,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)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