• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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, 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 
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 			}
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 
asn1_template_print_ctx(BIO * out,ASN1_VALUE ** fld,int indent,const ASN1_TEMPLATE * tt,const ASN1_PCTX * pctx)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 flags;
343 	size_t i;
344 	const char *sname, *fname;
345 	flags = tt->flags;
346 	if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
347 		sname = ASN1_ITEM_ptr(tt->item)->sname;
348 	else
349 		sname = NULL;
350 	if(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
351 		fname = NULL;
352 	else
353 		fname = tt->field_name;
354 	if(flags & ASN1_TFLG_SK_MASK)
355 		{
356 		const char *tname;
357 		ASN1_VALUE *skitem;
358 		STACK_OF(ASN1_VALUE) *stack;
359 
360 		/* SET OF, SEQUENCE OF */
361 		if (fname)
362 			{
363 			if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF)
364 				{
365 				if(flags & ASN1_TFLG_SET_OF)
366 					tname = "SET";
367 				else
368 					tname = "SEQUENCE";
369 				if (BIO_printf(out, "%*s%s OF %s {\n",
370 					indent, "", tname, tt->field_name) <= 0)
371 					return 0;
372 				}
373 			else if (BIO_printf(out, "%*s%s:\n", indent, "",
374 					fname) <= 0)
375 				return 0;
376 			}
377 		stack = (STACK_OF(ASN1_VALUE) *)*fld;
378 		for(i = 0; i < sk_ASN1_VALUE_num(stack); i++)
379 			{
380 			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
381 				return 0;
382 
383 			skitem = sk_ASN1_VALUE_value(stack, i);
384 			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
385 				ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
386 				return 0;
387 			}
388 		if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
389 				return 0;
390 		if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
391 			{
392 			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
393 				return 0;
394 			}
395 		return 1;
396 		}
397 	return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
398 							fname, sname, 0, pctx);
399 	}
400 
asn1_print_fsname(BIO * out,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)401 static int asn1_print_fsname(BIO *out, int indent,
402 			const char *fname, const char *sname,
403 			const ASN1_PCTX *pctx)
404 	{
405 	static char spaces[] = "                    ";
406 	const int nspaces = sizeof(spaces) - 1;
407 
408 #if 0
409 	if (!sname && !fname)
410 		return 1;
411 #endif
412 
413 	while (indent > nspaces)
414 		{
415 		if (BIO_write(out, spaces, nspaces) != nspaces)
416 			return 0;
417 		indent -= nspaces;
418 		}
419 	if (BIO_write(out, spaces, indent) != indent)
420 		return 0;
421 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
422 		sname = NULL;
423 	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
424 		fname = NULL;
425 	if (!sname && !fname)
426 		return 1;
427 	if (fname)
428 		{
429 		if (BIO_puts(out, fname) <= 0)
430 			return 0;
431 		}
432 	if (sname)
433 		{
434 		if (fname)
435 			{
436 			if (BIO_printf(out, " (%s)", sname) <= 0)
437 				return 0;
438 			}
439 		else
440 			{
441 			if (BIO_puts(out, sname) <= 0)
442 				return 0;
443 			}
444 		}
445 	if (BIO_write(out, ": ", 2) != 2)
446 		return 0;
447 	return 1;
448 	}
449 
asn1_print_boolean_ctx(BIO * out,int boolval,const ASN1_PCTX * pctx)450 static int asn1_print_boolean_ctx(BIO *out, int boolval,
451 							const ASN1_PCTX *pctx)
452 	{
453 	const char *str;
454 	switch (boolval)
455 		{
456 		case -1:
457 		str = "BOOL ABSENT";
458 		break;
459 
460 		case 0:
461 		str = "FALSE";
462 		break;
463 
464 		default:
465 		str = "TRUE";
466 		break;
467 
468 		}
469 
470 	if (BIO_puts(out, str) <= 0)
471 		return 0;
472 	return 1;
473 
474 	}
475 
asn1_print_integer_ctx(BIO * out,ASN1_INTEGER * str,const ASN1_PCTX * pctx)476 static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
477 						const ASN1_PCTX *pctx)
478 	{
479 	BIGNUM *bn = NULL;
480 	char *s = NULL;
481 	int ret = 1;
482 
483 	bn = ASN1_INTEGER_to_BN(str, NULL);
484 	if (bn == NULL) {
485 		return 0;
486 	}
487 	s = BN_bn2dec(bn);
488 	BN_free(bn);
489 	if (s == NULL) {
490 		return 0;
491 	}
492 
493 	if (BIO_puts(out, s) <= 0) {
494 		ret = 0;
495 	}
496 	OPENSSL_free(s);
497 	return ret;
498 	}
499 
asn1_print_oid_ctx(BIO * out,const ASN1_OBJECT * oid,const ASN1_PCTX * pctx)500 static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
501 						const ASN1_PCTX *pctx)
502 	{
503 	char objbuf[80];
504 	const char *ln;
505 	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
506 	if(!ln)
507 		ln = "";
508 	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
509 	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
510 		return 0;
511 	return 1;
512 	}
513 
asn1_print_obstring_ctx(BIO * out,ASN1_STRING * str,int indent,const ASN1_PCTX * pctx)514 static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
515 						const ASN1_PCTX *pctx)
516 	{
517 	if (str->type == V_ASN1_BIT_STRING)
518 		{
519 		if (BIO_printf(out, " (%ld unused bits)\n",
520 					str->flags & 0x7) <= 0)
521 				return 0;
522 		}
523 	else if (BIO_puts(out, "\n") <= 0)
524 		return 0;
525 	if (str->length > 0 && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
526 		return 0;
527 	}
528 	return 1;
529 	}
530 
asn1_primitive_print(BIO * out,ASN1_VALUE ** fld,const ASN1_ITEM * it,int indent,const char * fname,const char * sname,const ASN1_PCTX * pctx)531 static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
532 				const ASN1_ITEM *it, int indent,
533 				const char *fname, const char *sname,
534 				const ASN1_PCTX *pctx)
535 	{
536 	long utype;
537 	ASN1_STRING *str;
538 	int ret = 1, needlf = 1;
539 	const char *pname;
540 	const ASN1_PRIMITIVE_FUNCS *pf;
541 	pf = it->funcs;
542 	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
543 			return 0;
544 	if (pf && pf->prim_print)
545 		return pf->prim_print(out, fld, it, indent, pctx);
546 	str = (ASN1_STRING *)*fld;
547 	if (it->itype == ASN1_ITYPE_MSTRING)
548 		utype = str->type & ~V_ASN1_NEG;
549 	else
550 		utype = it->utype;
551 	if (utype == V_ASN1_ANY)
552 		{
553 		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
554 		utype = atype->type;
555 		fld = &atype->value.asn1_value;
556 		str = (ASN1_STRING *)*fld;
557 		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
558 			pname = NULL;
559 		else
560 			pname = ASN1_tag2str(utype);
561 		}
562 	else
563 		{
564 		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
565 			pname = ASN1_tag2str(utype);
566 		else
567 			pname = NULL;
568 		}
569 
570 	if (utype == V_ASN1_NULL)
571 		{
572 		if (BIO_puts(out, "NULL\n") <= 0)
573 			return 0;
574 		return 1;
575 		}
576 
577 	if (pname)
578 		{
579 		if (BIO_puts(out, pname) <= 0)
580 			return 0;
581 		if (BIO_puts(out, ":") <= 0)
582 			return 0;
583 		}
584 
585 	switch (utype)
586 		{
587 		case V_ASN1_BOOLEAN:
588 			{
589 			int boolval = *(int *)fld;
590 			if (boolval == -1)
591 				boolval = it->size;
592 			ret = asn1_print_boolean_ctx(out, boolval, pctx);
593 			}
594 		break;
595 
596 		case V_ASN1_INTEGER:
597 		case V_ASN1_ENUMERATED:
598 		ret = asn1_print_integer_ctx(out, str, pctx);
599 		break;
600 
601 		case V_ASN1_UTCTIME:
602 		ret = ASN1_UTCTIME_print(out, str);
603 		break;
604 
605 		case V_ASN1_GENERALIZEDTIME:
606 		ret = ASN1_GENERALIZEDTIME_print(out, str);
607 		break;
608 
609 		case V_ASN1_OBJECT:
610 		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
611 		break;
612 
613 		case V_ASN1_OCTET_STRING:
614 		case V_ASN1_BIT_STRING:
615 		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
616 		needlf = 0;
617 		break;
618 
619 		case V_ASN1_SEQUENCE:
620 		case V_ASN1_SET:
621 		case V_ASN1_OTHER:
622 		if (BIO_puts(out, "\n") <= 0)
623 			return 0;
624 		if (ASN1_parse_dump(out, str->data, str->length,
625 						indent, 0) <= 0)
626 			ret = 0;
627 		needlf = 0;
628 		break;
629 
630 		default:
631 		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
632 
633 		}
634 	if (!ret)
635 		return 0;
636 	if (needlf && BIO_puts(out, "\n") <= 0)
637 		return 0;
638 	return 1;
639 	}
640