Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/asn1/tasn_prn.c
Line
Count
Source (jump to first uncovered line)
1
/* tasn_prn.c */
2
/*
3
 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4
 * 2000.
5
 */
6
/* ====================================================================
7
 * Copyright (c) 2000,2005 The OpenSSL Project.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 *
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in
18
 *    the documentation and/or other materials provided with the
19
 *    distribution.
20
 *
21
 * 3. All advertising materials mentioning features or use of this
22
 *    software must display the following acknowledgment:
23
 *    "This product includes software developed by the OpenSSL Project
24
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25
 *
26
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27
 *    endorse or promote products derived from this software without
28
 *    prior written permission. For written permission, please contact
29
 *    licensing@OpenSSL.org.
30
 *
31
 * 5. Products derived from this software may not be called "OpenSSL"
32
 *    nor may "OpenSSL" appear in their names without prior written
33
 *    permission of the OpenSSL Project.
34
 *
35
 * 6. Redistributions of any form whatsoever must retain the following
36
 *    acknowledgment:
37
 *    "This product includes software developed by the OpenSSL Project
38
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51
 * OF THE POSSIBILITY OF SUCH DAMAGE.
52
 * ====================================================================
53
 *
54
 * This product includes cryptographic software written by Eric Young
55
 * (eay@cryptsoft.com).  This product includes software written by Tim
56
 * Hudson (tjh@cryptsoft.com).
57
 *
58
 */
59
60
#include <stddef.h>
61
#include "cryptlib.h"
62
#include <openssl/asn1.h>
63
#include <openssl/asn1t.h>
64
#include <openssl/objects.h>
65
#include <openssl/buffer.h>
66
#include <openssl/err.h>
67
#include <openssl/x509v3.h>
68
#include "asn1_locl.h"
69
70
/*
71
 * Print routines.
72
 */
73
74
/* ASN1_PCTX routines */
75
76
ASN1_PCTX default_pctx = {
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 *ASN1_PCTX_new(void)
85
0
{
86
0
    ASN1_PCTX *ret;
87
0
    ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
88
0
    if (ret == NULL) {
89
0
        ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
90
0
        return NULL;
91
0
    }
92
0
    ret->flags = 0;
93
0
    ret->nm_flags = 0;
94
0
    ret->cert_flags = 0;
95
0
    ret->oid_flags = 0;
96
0
    ret->str_flags = 0;
97
0
    return ret;
98
0
}
99
100
void ASN1_PCTX_free(ASN1_PCTX *p)
101
0
{
102
0
    OPENSSL_free(p);
103
0
}
104
105
unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
106
0
{
107
0
    return p->flags;
108
0
}
109
110
void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
111
0
{
112
0
    p->flags = flags;
113
0
}
114
115
unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
116
0
{
117
0
    return p->nm_flags;
118
0
}
119
120
void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
121
0
{
122
0
    p->nm_flags = flags;
123
0
}
124
125
unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
126
0
{
127
0
    return p->cert_flags;
128
0
}
129
130
void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
131
0
{
132
0
    p->cert_flags = flags;
133
0
}
134
135
unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
136
0
{
137
0
    return p->oid_flags;
138
0
}
139
140
void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
141
0
{
142
0
    p->oid_flags = flags;
143
0
}
144
145
unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
146
0
{
147
0
    return p->str_flags;
148
0
}
149
150
void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
151
0
{
152
0
    p->str_flags = flags;
153
0
}
154
155
/* Main print routines */
156
157
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
158
                               const ASN1_ITEM *it,
159
                               const char *fname, const char *sname,
160
                               int nohdr, const ASN1_PCTX *pctx);
161
162
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
163
                            const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
164
165
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
166
                                const ASN1_ITEM *it, int indent,
167
                                const char *fname, const char *sname,
168
                                const ASN1_PCTX *pctx);
169
170
static int asn1_print_fsname(BIO *out, int indent,
171
                             const char *fname, const char *sname,
172
                             const ASN1_PCTX *pctx);
173
174
int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
175
                    const ASN1_ITEM *it, const ASN1_PCTX *pctx)
176
0
{
177
0
    const char *sname;
178
0
    if (pctx == NULL)
179
0
        pctx = &default_pctx;
180
0
    if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
181
0
        sname = NULL;
182
0
    else
183
0
        sname = it->sname;
184
0
    return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
185
0
}
186
187
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
188
                               const ASN1_ITEM *it,
189
                               const char *fname, const char *sname,
190
                               int nohdr, const ASN1_PCTX *pctx)
191
0
{
192
0
    const ASN1_TEMPLATE *tt;
193
0
    const ASN1_EXTERN_FUNCS *ef;
194
0
    ASN1_VALUE **tmpfld;
195
0
    const ASN1_AUX *aux = it->funcs;
196
0
    ASN1_aux_cb *asn1_cb;
197
0
    ASN1_PRINT_ARG parg;
198
0
    int i;
199
0
    if (aux && aux->asn1_cb) {
200
0
        parg.out = out;
201
0
        parg.indent = indent;
202
0
        parg.pctx = pctx;
203
0
        asn1_cb = aux->asn1_cb;
204
0
    } else
205
0
        asn1_cb = 0;
206
207
0
   if (((it->itype != ASN1_ITYPE_PRIMITIVE)
208
0
       || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) {
209
0
        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
210
0
            if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
211
0
                return 0;
212
0
            if (BIO_puts(out, "<ABSENT>\n") <= 0)
213
0
                return 0;
214
0
        }
215
0
        return 1;
216
0
    }
217
218
0
    switch (it->itype) {
219
0
    case ASN1_ITYPE_PRIMITIVE:
220
0
        if (it->templates) {
221
0
            if (!asn1_template_print_ctx(out, fld, indent,
222
0
                                         it->templates, pctx))
223
0
                return 0;
224
0
            break;
225
0
        }
226
        /* fall thru */
227
0
    case ASN1_ITYPE_MSTRING:
228
0
        if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx))
229
0
            return 0;
230
0
        break;
231
232
0
    case ASN1_ITYPE_EXTERN:
233
0
        if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
234
0
            return 0;
235
        /* Use new style print routine if possible */
236
0
        ef = it->funcs;
237
0
        if (ef && ef->asn1_ex_print) {
238
0
            i = ef->asn1_ex_print(out, fld, indent, "", pctx);
239
0
            if (!i)
240
0
                return 0;
241
0
            if ((i == 2) && (BIO_puts(out, "\n") <= 0))
242
0
                return 0;
243
0
            return 1;
244
0
        } else if (sname &&
245
0
                   BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
246
0
            return 0;
247
0
        break;
248
249
0
    case ASN1_ITYPE_CHOICE:
250
#if 0
251
        if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
252
            return 0;
253
#endif
254
        /* CHOICE type, get selector */
255
0
        i = asn1_get_choice_selector(fld, it);
256
        /* This should never happen... */
257
0
        if ((i < 0) || (i >= it->tcount)) {
258
0
            if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
259
0
                return 0;
260
0
            return 1;
261
0
        }
262
0
        tt = it->templates + i;
263
0
        tmpfld = asn1_get_field_ptr(fld, tt);
264
0
        if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
265
0
            return 0;
266
0
        break;
267
268
0
    case ASN1_ITYPE_SEQUENCE:
269
0
    case ASN1_ITYPE_NDEF_SEQUENCE:
270
0
        if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
271
0
            return 0;
272
0
        if (fname || sname) {
273
0
            if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
274
0
                if (BIO_puts(out, " {\n") <= 0)
275
0
                    return 0;
276
0
            } else {
277
0
                if (BIO_puts(out, "\n") <= 0)
278
0
                    return 0;
279
0
            }
280
0
        }
281
282
0
        if (asn1_cb) {
283
0
            i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
284
0
            if (i == 0)
285
0
                return 0;
286
0
            if (i == 2)
287
0
                return 1;
288
0
        }
289
290
        /* Print each field entry */
291
0
        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
292
0
            const ASN1_TEMPLATE *seqtt;
293
0
            seqtt = asn1_do_adb(fld, tt, 1);
294
0
            if (!seqtt)
295
0
                return 0;
296
0
            tmpfld = asn1_get_field_ptr(fld, seqtt);
297
0
            if (!asn1_template_print_ctx(out, tmpfld,
298
0
                                         indent + 2, seqtt, pctx))
299
0
                return 0;
300
0
        }
301
0
        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
302
0
            if (BIO_printf(out, "%*s}\n", indent, "") < 0)
303
0
                return 0;
304
0
        }
305
306
0
        if (asn1_cb) {
307
0
            i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
308
0
            if (i == 0)
309
0
                return 0;
310
0
        }
311
0
        break;
312
313
0
    default:
314
0
        BIO_printf(out, "Unprocessed type %d\n", it->itype);
315
0
        return 0;
316
0
    }
317
318
0
    return 1;
319
0
}
320
321
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
322
                            const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
323
0
{
324
0
    int i, flags;
325
0
    const char *sname, *fname;
326
0
    flags = tt->flags;
327
0
    if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
328
0
        sname = ASN1_ITEM_ptr(tt->item)->sname;
329
0
    else
330
0
        sname = NULL;
331
0
    if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
332
0
        fname = NULL;
333
0
    else
334
0
        fname = tt->field_name;
335
0
    if (flags & ASN1_TFLG_SK_MASK) {
336
0
        char *tname;
337
0
        ASN1_VALUE *skitem;
338
0
        STACK_OF(ASN1_VALUE) *stack;
339
340
        /* SET OF, SEQUENCE OF */
341
0
        if (fname) {
342
0
            if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
343
0
                if (flags & ASN1_TFLG_SET_OF)
344
0
                    tname = "SET";
345
0
                else
346
0
                    tname = "SEQUENCE";
347
0
                if (BIO_printf(out, "%*s%s OF %s {\n",
348
0
                               indent, "", tname, tt->field_name) <= 0)
349
0
                    return 0;
350
0
            } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
351
0
                return 0;
352
0
        }
353
0
        stack = (STACK_OF(ASN1_VALUE) *)*fld;
354
0
        for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
355
0
            if ((i > 0) && (BIO_puts(out, "\n") <= 0))
356
0
                return 0;
357
358
0
            skitem = sk_ASN1_VALUE_value(stack, i);
359
0
            if (!asn1_item_print_ctx(out, &skitem, indent + 2,
360
0
                                     ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
361
0
                                     pctx))
362
0
                return 0;
363
0
        }
364
0
        if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
365
0
            return 0;
366
0
        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
367
0
            if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
368
0
                return 0;
369
0
        }
370
0
        return 1;
371
0
    }
372
0
    return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
373
0
                               fname, sname, 0, pctx);
374
0
}
375
376
static int asn1_print_fsname(BIO *out, int indent,
377
                             const char *fname, const char *sname,
378
                             const ASN1_PCTX *pctx)
379
0
{
380
0
    static char spaces[] = "                    ";
381
0
    const int nspaces = sizeof(spaces) - 1;
382
383
#if 0
384
    if (!sname && !fname)
385
        return 1;
386
#endif
387
388
0
    while (indent > nspaces) {
389
0
        if (BIO_write(out, spaces, nspaces) != nspaces)
390
0
            return 0;
391
0
        indent -= nspaces;
392
0
    }
393
0
    if (BIO_write(out, spaces, indent) != indent)
394
0
        return 0;
395
0
    if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
396
0
        sname = NULL;
397
0
    if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
398
0
        fname = NULL;
399
0
    if (!sname && !fname)
400
0
        return 1;
401
0
    if (fname) {
402
0
        if (BIO_puts(out, fname) <= 0)
403
0
            return 0;
404
0
    }
405
0
    if (sname) {
406
0
        if (fname) {
407
0
            if (BIO_printf(out, " (%s)", sname) <= 0)
408
0
                return 0;
409
0
        } else {
410
0
            if (BIO_puts(out, sname) <= 0)
411
0
                return 0;
412
0
        }
413
0
    }
414
0
    if (BIO_write(out, ": ", 2) != 2)
415
0
        return 0;
416
0
    return 1;
417
0
}
418
419
static int asn1_print_boolean_ctx(BIO *out, int boolval,
420
                                  const ASN1_PCTX *pctx)
421
0
{
422
0
    const char *str;
423
0
    switch (boolval) {
424
0
    case -1:
425
0
        str = "BOOL ABSENT";
426
0
        break;
427
428
0
    case 0:
429
0
        str = "FALSE";
430
0
        break;
431
432
0
    default:
433
0
        str = "TRUE";
434
0
        break;
435
436
0
    }
437
438
0
    if (BIO_puts(out, str) <= 0)
439
0
        return 0;
440
0
    return 1;
441
442
0
}
443
444
static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
445
                                  const ASN1_PCTX *pctx)
446
0
{
447
0
    char *s;
448
0
    int ret = 1;
449
0
    s = i2s_ASN1_INTEGER(NULL, str);
450
0
    if (s == NULL)
451
0
        return 0;
452
0
    if (BIO_puts(out, s) <= 0)
453
0
        ret = 0;
454
0
    OPENSSL_free(s);
455
0
    return ret;
456
0
}
457
458
static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
459
                              const ASN1_PCTX *pctx)
460
0
{
461
0
    char objbuf[80];
462
0
    const char *ln;
463
0
    ln = OBJ_nid2ln(OBJ_obj2nid(oid));
464
0
    if (!ln)
465
0
        ln = "";
466
0
    OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
467
0
    if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
468
0
        return 0;
469
0
    return 1;
470
0
}
471
472
static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
473
                                   const ASN1_PCTX *pctx)
474
0
{
475
0
    if (str->type == V_ASN1_BIT_STRING) {
476
0
        if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0)
477
0
            return 0;
478
0
    } else if (BIO_puts(out, "\n") <= 0)
479
0
        return 0;
480
0
    if ((str->length > 0)
481
0
        && BIO_dump_indent(out, (char *)str->data, str->length,
482
0
                           indent + 2) <= 0)
483
0
        return 0;
484
0
    return 1;
485
0
}
486
487
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
488
                                const ASN1_ITEM *it, int indent,
489
                                const char *fname, const char *sname,
490
                                const ASN1_PCTX *pctx)
491
0
{
492
0
    long utype;
493
0
    ASN1_STRING *str;
494
0
    int ret = 1, needlf = 1;
495
0
    const char *pname;
496
0
    const ASN1_PRIMITIVE_FUNCS *pf;
497
0
    pf = it->funcs;
498
0
    if (!asn1_print_fsname(out, indent, fname, sname, pctx))
499
0
        return 0;
500
0
    if (pf && pf->prim_print)
501
0
        return pf->prim_print(out, fld, it, indent, pctx);
502
0
    if (it->itype == ASN1_ITYPE_MSTRING) {
503
0
        str = (ASN1_STRING *)*fld;
504
0
        utype = str->type & ~V_ASN1_NEG;
505
0
    } else {
506
0
        utype = it->utype;
507
0
        if (utype == V_ASN1_BOOLEAN)
508
0
            str = NULL;
509
0
        else
510
0
            str = (ASN1_STRING *)*fld;
511
0
    }
512
0
    if (utype == V_ASN1_ANY) {
513
0
        ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
514
0
        utype = atype->type;
515
0
        fld = &atype->value.asn1_value;
516
0
        str = (ASN1_STRING *)*fld;
517
0
        if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
518
0
            pname = NULL;
519
0
        else
520
0
            pname = ASN1_tag2str(utype);
521
0
    } else {
522
0
        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
523
0
            pname = ASN1_tag2str(utype);
524
0
        else
525
0
            pname = NULL;
526
0
    }
527
528
0
    if (utype == V_ASN1_NULL) {
529
0
        if (BIO_puts(out, "NULL\n") <= 0)
530
0
            return 0;
531
0
        return 1;
532
0
    }
533
534
0
    if (pname) {
535
0
        if (BIO_puts(out, pname) <= 0)
536
0
            return 0;
537
0
        if (BIO_puts(out, ":") <= 0)
538
0
            return 0;
539
0
    }
540
541
0
    switch (utype) {
542
0
    case V_ASN1_BOOLEAN:
543
0
        {
544
0
            int boolval = *(int *)fld;
545
0
            if (boolval == -1)
546
0
                boolval = it->size;
547
0
            ret = asn1_print_boolean_ctx(out, boolval, pctx);
548
0
        }
549
0
        break;
550
551
0
    case V_ASN1_INTEGER:
552
0
    case V_ASN1_ENUMERATED:
553
0
        ret = asn1_print_integer_ctx(out, str, pctx);
554
0
        break;
555
556
0
    case V_ASN1_UTCTIME:
557
0
        ret = ASN1_UTCTIME_print(out, str);
558
0
        break;
559
560
0
    case V_ASN1_GENERALIZEDTIME:
561
0
        ret = ASN1_GENERALIZEDTIME_print(out, str);
562
0
        break;
563
564
0
    case V_ASN1_OBJECT:
565
0
        ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
566
0
        break;
567
568
0
    case V_ASN1_OCTET_STRING:
569
0
    case V_ASN1_BIT_STRING:
570
0
        ret = asn1_print_obstring_ctx(out, str, indent, pctx);
571
0
        needlf = 0;
572
0
        break;
573
574
0
    case V_ASN1_SEQUENCE:
575
0
    case V_ASN1_SET:
576
0
    case V_ASN1_OTHER:
577
0
        if (BIO_puts(out, "\n") <= 0)
578
0
            return 0;
579
0
        if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0)
580
0
            ret = 0;
581
0
        needlf = 0;
582
0
        break;
583
584
0
    default:
585
0
        ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
586
587
0
    }
588
0
    if (!ret)
589
0
        return 0;
590
0
    if (needlf && BIO_puts(out, "\n") <= 0)
591
0
        return 0;
592
0
    return 1;
593
0
}