Coverage Report

Created: 2025-11-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/encode_decode/encoder_lib.c
Line
Count
Source
1
/*
2
 * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <ctype.h>
11
12
#include <openssl/core_names.h>
13
#include <openssl/bio.h>
14
#include <openssl/encoder.h>
15
#include <openssl/buffer.h>
16
#include <openssl/params.h>
17
#include <openssl/provider.h>
18
#include <openssl/trace.h>
19
#include <crypto/bn.h>
20
#include "internal/bio.h"
21
#include "internal/ffc.h"
22
#include "internal/provider.h"
23
#include "internal/encoder.h"
24
#include "encoder_local.h"
25
26
/* Number of octets per line */
27
0
#define LABELED_BUF_PRINT_WIDTH    15
28
29
# ifdef SIXTY_FOUR_BIT_LONG
30
#  define BN_FMTu "%lu"
31
#  define BN_FMTx "%lx"
32
# endif
33
34
# ifdef SIXTY_FOUR_BIT
35
#  define BN_FMTu "%llu"
36
#  define BN_FMTx "%llx"
37
# endif
38
39
# ifdef THIRTY_TWO_BIT
40
#  define BN_FMTu "%u"
41
#  define BN_FMTx "%x"
42
# endif
43
44
struct encoder_process_data_st {
45
    OSSL_ENCODER_CTX *ctx;
46
47
    /* Current BIO */
48
    BIO *bio;
49
50
    /* Index of the current encoder instance to be processed */
51
    int current_encoder_inst_index;
52
53
    /* Processing data passed down through recursion */
54
    int level;                   /* Recursion level */
55
    OSSL_ENCODER_INSTANCE *next_encoder_inst;
56
    int count_output_structure;
57
58
    /* Processing data passed up through recursion */
59
    OSSL_ENCODER_INSTANCE *prev_encoder_inst;
60
    unsigned char *running_output;
61
    size_t running_output_length;
62
    /* Data type = the name of the first succeeding encoder implementation */
63
    const char *data_type;
64
};
65
66
static int encoder_process(struct encoder_process_data_st *data);
67
68
int OSSL_ENCODER_to_bio(OSSL_ENCODER_CTX *ctx, BIO *out)
69
0
{
70
0
    struct encoder_process_data_st data;
71
72
0
    memset(&data, 0, sizeof(data));
73
0
    data.ctx = ctx;
74
0
    data.bio = out;
75
0
    data.current_encoder_inst_index = OSSL_ENCODER_CTX_get_num_encoders(ctx);
76
77
0
    if (data.current_encoder_inst_index == 0) {
78
0
        ERR_raise_data(ERR_LIB_OSSL_ENCODER, OSSL_ENCODER_R_ENCODER_NOT_FOUND,
79
0
                       "No encoders were found. For standard encoders you need "
80
0
                       "at least one of the default or base providers "
81
0
                       "available. Did you forget to load them?");
82
0
        return 0;
83
0
    }
84
85
0
    if (ctx->cleanup == NULL || ctx->construct == NULL) {
86
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INIT_FAIL);
87
0
        return 0;
88
0
    }
89
90
0
    return encoder_process(&data) > 0;
91
0
}
92
93
#ifndef OPENSSL_NO_STDIO
94
static BIO *bio_from_file(FILE *fp)
95
0
{
96
0
    BIO *b;
97
98
0
    if ((b = BIO_new(BIO_s_file())) == NULL) {
99
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_BUF_LIB);
100
0
        return NULL;
101
0
    }
102
0
    BIO_set_fp(b, fp, BIO_NOCLOSE);
103
0
    return b;
104
0
}
105
106
int OSSL_ENCODER_to_fp(OSSL_ENCODER_CTX *ctx, FILE *fp)
107
0
{
108
0
    BIO *b = bio_from_file(fp);
109
0
    int ret = 0;
110
111
0
    if (b != NULL)
112
0
        ret = OSSL_ENCODER_to_bio(ctx, b);
113
114
0
    BIO_free(b);
115
0
    return ret;
116
0
}
117
#endif
118
119
int OSSL_ENCODER_to_data(OSSL_ENCODER_CTX *ctx, unsigned char **pdata,
120
                         size_t *pdata_len)
121
0
{
122
0
    BIO *out;
123
0
    BUF_MEM *buf = NULL;
124
0
    int ret = 0;
125
126
0
    if (pdata_len == NULL) {
127
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
128
0
        return 0;
129
0
    }
130
131
0
    out = BIO_new(BIO_s_mem());
132
133
0
    if (out != NULL
134
0
        && OSSL_ENCODER_to_bio(ctx, out)
135
0
        && BIO_get_mem_ptr(out, &buf) > 0) {
136
0
        ret = 1; /* Hope for the best. A too small buffer will clear this */
137
138
0
        if (pdata != NULL && *pdata != NULL) {
139
0
            if (*pdata_len < buf->length)
140
                /*
141
                 * It's tempting to do |*pdata_len = (size_t)buf->length|
142
                 * However, it's believed to be confusing more than helpful,
143
                 * so we don't.
144
                 */
145
0
                ret = 0;
146
0
            else
147
0
                *pdata_len -= buf->length;
148
0
        } else {
149
            /* The buffer with the right size is already allocated for us */
150
0
            *pdata_len = (size_t)buf->length;
151
0
        }
152
153
0
        if (ret) {
154
0
            if (pdata != NULL) {
155
0
                if (*pdata != NULL) {
156
0
                    memcpy(*pdata, buf->data, buf->length);
157
0
                    *pdata += buf->length;
158
0
                } else {
159
                    /* In this case, we steal the data from BIO_s_mem() */
160
0
                    *pdata = (unsigned char *)buf->data;
161
0
                    buf->data = NULL;
162
0
                }
163
0
            }
164
0
        }
165
0
    }
166
0
    BIO_free(out);
167
0
    return ret;
168
0
}
169
170
int OSSL_ENCODER_CTX_set_selection(OSSL_ENCODER_CTX *ctx, int selection)
171
0
{
172
0
    if (ctx == NULL) {
173
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
174
0
        return 0;
175
0
    }
176
177
0
    if (ctx->finalized != 0) {
178
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
179
0
        return 0;
180
0
    }
181
182
0
    if (selection == 0) {
183
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
184
0
        return 0;
185
0
    }
186
187
0
    ctx->selection = selection;
188
0
    return 1;
189
0
}
190
191
int OSSL_ENCODER_CTX_set_output_type(OSSL_ENCODER_CTX *ctx,
192
                                     const char *output_type)
193
0
{
194
0
    if (ctx == NULL || output_type == NULL) {
195
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
196
0
        return 0;
197
0
    }
198
199
0
    if (ctx->finalized != 0) {
200
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
201
0
        return 0;
202
0
    }
203
204
0
    ctx->output_type = output_type;
205
0
    return 1;
206
0
}
207
208
int OSSL_ENCODER_CTX_set_output_structure(OSSL_ENCODER_CTX *ctx,
209
                                          const char *output_structure)
210
0
{
211
0
    if (ctx == NULL || output_structure == NULL) {
212
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
213
0
        return 0;
214
0
    }
215
216
0
    if (ctx->finalized != 0) {
217
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
218
0
        return 0;
219
0
    }
220
221
0
    ctx->output_structure = output_structure;
222
0
    return 1;
223
0
}
224
225
static OSSL_ENCODER_INSTANCE *ossl_encoder_instance_new(OSSL_ENCODER *encoder,
226
                                                        void *encoderctx)
227
0
{
228
0
    OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
229
0
    const OSSL_PROVIDER *prov;
230
0
    OSSL_LIB_CTX *libctx;
231
0
    const OSSL_PROPERTY_LIST *props;
232
0
    const OSSL_PROPERTY_DEFINITION *prop;
233
234
0
    if (encoder == NULL) {
235
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
236
0
        return 0;
237
0
    }
238
239
0
    if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL)
240
0
        return 0;
241
242
0
    if (!OSSL_ENCODER_up_ref(encoder)) {
243
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
244
0
        goto err;
245
0
    }
246
247
0
    prov = OSSL_ENCODER_get0_provider(encoder);
248
0
    libctx = ossl_provider_libctx(prov);
249
0
    props = ossl_encoder_parsed_properties(encoder);
250
0
    if (props == NULL) {
251
0
        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
252
0
                       "there are no property definitions with encoder %s",
253
0
                       OSSL_ENCODER_get0_name(encoder));
254
0
        goto err;
255
0
    }
256
257
    /* The "output" property is mandatory */
258
0
    prop = ossl_property_find_property(props, libctx, "output");
259
0
    encoder_inst->output_type = ossl_property_get_string_value(libctx, prop);
260
0
    if (encoder_inst->output_type == NULL) {
261
0
        ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
262
0
                       "the mandatory 'output' property is missing "
263
0
                       "for encoder %s (properties: %s)",
264
0
                       OSSL_ENCODER_get0_name(encoder),
265
0
                       OSSL_ENCODER_get0_properties(encoder));
266
0
        goto err;
267
0
    }
268
269
    /* The "structure" property is optional */
270
0
    prop = ossl_property_find_property(props, libctx, "structure");
271
0
    if (prop != NULL)
272
0
        encoder_inst->output_structure
273
0
            = ossl_property_get_string_value(libctx, prop);
274
275
0
    encoder_inst->encoder = encoder;
276
0
    encoder_inst->encoderctx = encoderctx;
277
0
    return encoder_inst;
278
0
 err:
279
0
    ossl_encoder_instance_free(encoder_inst);
280
0
    return NULL;
281
0
}
282
283
void ossl_encoder_instance_free(OSSL_ENCODER_INSTANCE *encoder_inst)
284
0
{
285
0
    if (encoder_inst != NULL) {
286
0
        if (encoder_inst->encoder != NULL)
287
0
            encoder_inst->encoder->freectx(encoder_inst->encoderctx);
288
0
        encoder_inst->encoderctx = NULL;
289
0
        OSSL_ENCODER_free(encoder_inst->encoder);
290
0
        encoder_inst->encoder = NULL;
291
0
        OPENSSL_free(encoder_inst);
292
0
    }
293
0
}
294
295
static int ossl_encoder_ctx_add_encoder_inst(OSSL_ENCODER_CTX *ctx,
296
                                             OSSL_ENCODER_INSTANCE *ei)
297
0
{
298
0
    int ok;
299
300
0
    if (ctx->encoder_insts == NULL
301
0
        && (ctx->encoder_insts =
302
0
            sk_OSSL_ENCODER_INSTANCE_new_null()) == NULL) {
303
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_CRYPTO_LIB);
304
0
        return 0;
305
0
    }
306
307
0
    ok = (sk_OSSL_ENCODER_INSTANCE_push(ctx->encoder_insts, ei) > 0);
308
0
    if (ok) {
309
0
        OSSL_TRACE_BEGIN(ENCODER) {
310
0
            BIO_printf(trc_out,
311
0
                       "(ctx %p) Added encoder instance %p (encoder %p):\n"
312
0
                       "    %s with %s\n",
313
0
                       (void *)ctx, (void *)ei, (void *)ei->encoder,
314
0
                       OSSL_ENCODER_get0_name(ei->encoder),
315
0
                       OSSL_ENCODER_get0_properties(ei->encoder));
316
0
        } OSSL_TRACE_END(ENCODER);
317
0
    }
318
0
    return ok;
319
0
}
320
321
int OSSL_ENCODER_CTX_add_encoder(OSSL_ENCODER_CTX *ctx, OSSL_ENCODER *encoder)
322
0
{
323
0
    OSSL_ENCODER_INSTANCE *encoder_inst = NULL;
324
0
    const OSSL_PROVIDER *prov = NULL;
325
0
    void *encoderctx = NULL;
326
0
    void *provctx = NULL;
327
328
0
    if (ctx == NULL || encoder == NULL) {
329
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
330
0
        return 0;
331
0
    }
332
333
0
    if (ctx->finalized != 0) {
334
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
335
0
        return 0;
336
0
    }
337
338
0
    prov = OSSL_ENCODER_get0_provider(encoder);
339
0
    provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
340
341
0
    if ((encoderctx = encoder->newctx(provctx)) == NULL
342
0
        || (encoder_inst =
343
0
            ossl_encoder_instance_new(encoder, encoderctx)) == NULL)
344
0
        goto err;
345
    /* Avoid double free of encoderctx on further errors */
346
0
    encoderctx = NULL;
347
348
0
    if (!ossl_encoder_ctx_add_encoder_inst(ctx, encoder_inst))
349
0
        goto err;
350
351
0
    return 1;
352
0
 err:
353
0
    ossl_encoder_instance_free(encoder_inst);
354
0
    if (encoderctx != NULL)
355
0
        encoder->freectx(encoderctx);
356
0
    return 0;
357
0
}
358
359
int OSSL_ENCODER_CTX_add_extra(OSSL_ENCODER_CTX *ctx,
360
                               OSSL_LIB_CTX *libctx, const char *propq)
361
0
{
362
0
    if (ctx == NULL) {
363
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
364
0
        return 0;
365
0
    }
366
367
0
    if (ctx->finalized != 0) {
368
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
369
0
        return 0;
370
0
    }
371
372
0
    return 1;
373
0
}
374
375
int OSSL_ENCODER_CTX_get_num_encoders(OSSL_ENCODER_CTX *ctx)
376
0
{
377
0
    if (ctx == NULL || ctx->encoder_insts == NULL)
378
0
        return 0;
379
0
    return sk_OSSL_ENCODER_INSTANCE_num(ctx->encoder_insts);
380
0
}
381
382
int OSSL_ENCODER_CTX_set_construct(OSSL_ENCODER_CTX *ctx,
383
                                   OSSL_ENCODER_CONSTRUCT *construct)
384
0
{
385
0
    if (ctx == NULL) {
386
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
387
0
        return 0;
388
0
    }
389
390
0
    if (ctx->finalized != 0) {
391
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
392
0
        return 0;
393
0
    }
394
395
0
    ctx->construct = construct;
396
0
    return 1;
397
0
}
398
399
int OSSL_ENCODER_CTX_set_construct_data(OSSL_ENCODER_CTX *ctx,
400
                                        void *construct_data)
401
0
{
402
0
    if (ctx == NULL) {
403
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
404
0
        return 0;
405
0
    }
406
407
0
    if (ctx->finalized != 0) {
408
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
409
0
        return 0;
410
0
    }
411
412
0
    ctx->construct_data = construct_data;
413
0
    return 1;
414
0
}
415
416
int OSSL_ENCODER_CTX_set_cleanup(OSSL_ENCODER_CTX *ctx,
417
                                 OSSL_ENCODER_CLEANUP *cleanup)
418
0
{
419
0
    if (ctx == NULL) {
420
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
421
0
        return 0;
422
0
    }
423
424
0
    if (ctx->finalized != 0) {
425
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
426
0
        return 0;
427
0
    }
428
429
0
    ctx->cleanup = cleanup;
430
0
    return 1;
431
0
}
432
433
int OSSL_ENCODER_CTX_set_finalized(OSSL_ENCODER_CTX *ctx)
434
0
{
435
0
    if (ctx == NULL) {
436
0
        ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
437
0
        return 0;
438
0
    }
439
440
0
    ctx->finalized = 1;
441
0
    return 1;
442
0
}
443
444
int OSSL_ENCODER_CTX_get_finalized(OSSL_ENCODER_CTX *ctx)
445
0
{
446
0
    if (ctx == NULL)
447
0
        return 0;
448
449
0
    return ctx->finalized;
450
0
}
451
452
OSSL_ENCODER *
453
OSSL_ENCODER_INSTANCE_get_encoder(OSSL_ENCODER_INSTANCE *encoder_inst)
454
0
{
455
0
    if (encoder_inst == NULL)
456
0
        return NULL;
457
0
    return encoder_inst->encoder;
458
0
}
459
460
void *
461
OSSL_ENCODER_INSTANCE_get_encoder_ctx(OSSL_ENCODER_INSTANCE *encoder_inst)
462
0
{
463
0
    if (encoder_inst == NULL)
464
0
        return NULL;
465
0
    return encoder_inst->encoderctx;
466
0
}
467
468
const char *
469
OSSL_ENCODER_INSTANCE_get_output_type(OSSL_ENCODER_INSTANCE *encoder_inst)
470
0
{
471
0
    if (encoder_inst == NULL)
472
0
        return NULL;
473
0
    return encoder_inst->output_type;
474
0
}
475
476
const char *
477
OSSL_ENCODER_INSTANCE_get_output_structure(OSSL_ENCODER_INSTANCE *encoder_inst)
478
0
{
479
0
    if (encoder_inst == NULL)
480
0
        return NULL;
481
0
    return encoder_inst->output_structure;
482
0
}
483
484
static int encoder_process(struct encoder_process_data_st *data)
485
0
{
486
0
    OSSL_ENCODER_INSTANCE *current_encoder_inst = NULL;
487
0
    OSSL_ENCODER *current_encoder = NULL;
488
0
    OSSL_ENCODER_CTX *current_encoder_ctx = NULL;
489
0
    BIO *allocated_out = NULL;
490
0
    const void *original_data = NULL;
491
0
    OSSL_PARAM abstract[10];
492
0
    const OSSL_PARAM *current_abstract = NULL;
493
0
    int i;
494
0
    int ok = -1;  /* -1 signifies that the lookup loop gave nothing */
495
0
    int top = 0;
496
497
0
    if (data->next_encoder_inst == NULL) {
498
        /* First iteration, where we prepare for what is to come */
499
500
0
        data->count_output_structure =
501
0
            data->ctx->output_structure == NULL ? -1 : 0;
502
0
        top = 1;
503
0
    }
504
505
0
    for (i = data->current_encoder_inst_index; i-- > 0;) {
506
0
        OSSL_ENCODER *next_encoder = NULL;
507
0
        const char *current_output_type;
508
0
        const char *current_output_structure;
509
0
        struct encoder_process_data_st new_data;
510
511
0
        if (!top)
512
0
            next_encoder =
513
0
                OSSL_ENCODER_INSTANCE_get_encoder(data->next_encoder_inst);
514
515
0
        current_encoder_inst =
516
0
            sk_OSSL_ENCODER_INSTANCE_value(data->ctx->encoder_insts, i);
517
0
        current_encoder =
518
0
            OSSL_ENCODER_INSTANCE_get_encoder(current_encoder_inst);
519
0
        current_encoder_ctx =
520
0
            OSSL_ENCODER_INSTANCE_get_encoder_ctx(current_encoder_inst);
521
0
        current_output_type =
522
0
            OSSL_ENCODER_INSTANCE_get_output_type(current_encoder_inst);
523
0
        current_output_structure =
524
0
            OSSL_ENCODER_INSTANCE_get_output_structure(current_encoder_inst);
525
0
        memset(&new_data, 0, sizeof(new_data));
526
0
        new_data.ctx = data->ctx;
527
0
        new_data.current_encoder_inst_index = i;
528
0
        new_data.next_encoder_inst = current_encoder_inst;
529
0
        new_data.count_output_structure = data->count_output_structure;
530
0
        new_data.level = data->level + 1;
531
532
0
        OSSL_TRACE_BEGIN(ENCODER) {
533
0
            BIO_printf(trc_out,
534
0
                       "[%d] (ctx %p) Considering encoder instance %p (encoder %p)\n",
535
0
                       data->level, (void *)data->ctx,
536
0
                       (void *)current_encoder_inst, (void *)current_encoder);
537
0
        } OSSL_TRACE_END(ENCODER);
538
539
        /*
540
         * If this is the top call, we check if the output type of the current
541
         * encoder matches the desired output type.
542
         * If this isn't the top call, i.e. this is deeper in the recursion,
543
         * we instead check if the output type of the current encoder matches
544
         * the name of the next encoder (the one found by the parent call).
545
         */
546
0
        if (top) {
547
0
            if (data->ctx->output_type != NULL
548
0
                && OPENSSL_strcasecmp(current_output_type,
549
0
                                      data->ctx->output_type) != 0) {
550
0
                OSSL_TRACE_BEGIN(ENCODER) {
551
0
                    BIO_printf(trc_out,
552
0
                               "[%d]    Skipping because current encoder output type (%s) != desired output type (%s)\n",
553
0
                               data->level,
554
0
                               current_output_type, data->ctx->output_type);
555
0
                } OSSL_TRACE_END(ENCODER);
556
0
                continue;
557
0
            }
558
0
        } else {
559
0
            if (!OSSL_ENCODER_is_a(next_encoder, current_output_type)) {
560
0
                OSSL_TRACE_BEGIN(ENCODER) {
561
0
                    BIO_printf(trc_out,
562
0
                               "[%d]    Skipping because current encoder output type (%s) != name of encoder %p\n",
563
0
                               data->level,
564
0
                               current_output_type, (void *)next_encoder);
565
0
                } OSSL_TRACE_END(ENCODER);
566
0
                continue;
567
0
            }
568
0
        }
569
570
        /*
571
         * If the caller and the current encoder specify an output structure,
572
         * Check if they match.  If they do, count the match, otherwise skip
573
         * the current encoder.
574
         */
575
0
        if (data->ctx->output_structure != NULL
576
0
            && current_output_structure != NULL) {
577
0
            if (OPENSSL_strcasecmp(data->ctx->output_structure,
578
0
                                   current_output_structure) != 0) {
579
0
                OSSL_TRACE_BEGIN(ENCODER) {
580
0
                    BIO_printf(trc_out,
581
0
                               "[%d]    Skipping because current encoder output structure (%s) != ctx output structure (%s)\n",
582
0
                               data->level,
583
0
                               current_output_structure,
584
0
                               data->ctx->output_structure);
585
0
                } OSSL_TRACE_END(ENCODER);
586
0
                continue;
587
0
            }
588
589
0
            data->count_output_structure++;
590
0
        }
591
592
        /*
593
         * Recurse to process the encoder implementations before the current
594
         * one.
595
         */
596
0
        ok = encoder_process(&new_data);
597
598
0
        data->prev_encoder_inst = new_data.prev_encoder_inst;
599
0
        data->running_output = new_data.running_output;
600
0
        data->running_output_length = new_data.running_output_length;
601
602
        /*
603
         * ok == -1     means that the recursion call above gave no further
604
         *              encoders, and that the one we're currently at should
605
         *              be tried.
606
         * ok == 0      means that something failed in the recursion call
607
         *              above, making the result unsuitable for a chain.
608
         *              In this case, we simply continue to try finding a
609
         *              suitable encoder at this recursion level.
610
         * ok == 1      means that the recursion call was successful, and we
611
         *              try to use the result at this recursion level.
612
         */
613
0
        if (ok != 0)
614
0
            break;
615
616
0
        OSSL_TRACE_BEGIN(ENCODER) {
617
0
            BIO_printf(trc_out,
618
0
                       "[%d]    Skipping because recursion level %d failed\n",
619
0
                       data->level, new_data.level);
620
0
        } OSSL_TRACE_END(ENCODER);
621
0
    }
622
623
    /*
624
     * If |i < 0|, we didn't find any useful encoder in this recursion, so
625
     * we do the rest of the process only if |i >= 0|.
626
     */
627
0
    if (i < 0) {
628
0
        ok = -1;
629
630
0
        OSSL_TRACE_BEGIN(ENCODER) {
631
0
            BIO_printf(trc_out,
632
0
                       "[%d] (ctx %p) No suitable encoder found\n",
633
0
                       data->level, (void *)data->ctx);
634
0
        } OSSL_TRACE_END(ENCODER);
635
0
    } else {
636
        /* Preparations */
637
638
0
        switch (ok) {
639
0
        case 0:
640
0
            break;
641
0
        case -1:
642
            /*
643
             * We have reached the beginning of the encoder instance sequence,
644
             * so we prepare the object to be encoded.
645
             */
646
647
            /*
648
             * |data->count_output_structure| is one of these values:
649
             *
650
             * -1       There is no desired output structure
651
             *  0       There is a desired output structure, and it wasn't
652
             *          matched by any of the encoder instances that were
653
             *          considered
654
             * >0       There is a desired output structure, and at least one
655
             *          of the encoder instances matched it
656
             */
657
0
            if (data->count_output_structure == 0)
658
0
                return 0;
659
660
0
            original_data =
661
0
                data->ctx->construct(current_encoder_inst,
662
0
                                     data->ctx->construct_data);
663
664
            /* Also set the data type, using the encoder implementation name */
665
0
            data->data_type = OSSL_ENCODER_get0_name(current_encoder);
666
667
            /* Assume that the constructor recorded an error */
668
0
            if (original_data != NULL)
669
0
                ok = 1;
670
0
            else
671
0
                ok = 0;
672
0
            break;
673
0
        case 1:
674
0
            if (!ossl_assert(data->running_output != NULL)) {
675
0
                ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
676
0
                ok = 0;
677
0
                break;
678
0
            }
679
680
0
            {
681
                /*
682
                 * Create an object abstraction from the latest output, which
683
                 * was stolen from the previous round.
684
                 */
685
686
0
                OSSL_PARAM *abstract_p = abstract;
687
0
                const char *prev_output_structure =
688
0
                    OSSL_ENCODER_INSTANCE_get_output_structure(data->prev_encoder_inst);
689
690
0
                *abstract_p++ =
691
0
                    OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
692
0
                                                     (char *)data->data_type, 0);
693
0
                if (prev_output_structure != NULL)
694
0
                    *abstract_p++ =
695
0
                        OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
696
0
                                                         (char *)prev_output_structure,
697
0
                                                         0);
698
0
                *abstract_p++ =
699
0
                    OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA,
700
0
                                                      data->running_output,
701
0
                                                      data->running_output_length);
702
0
                *abstract_p = OSSL_PARAM_construct_end();
703
0
                current_abstract = abstract;
704
0
            }
705
0
            break;
706
0
        }
707
708
        /* Calling the encoder implementation */
709
710
0
        if (ok) {
711
0
            OSSL_CORE_BIO *cbio = NULL;
712
0
            BIO *current_out = NULL;
713
714
            /*
715
             * If we're at the last encoder instance to use, we're setting up
716
             * final output.  Otherwise, set up an intermediary memory output.
717
             */
718
0
            if (top)
719
0
                current_out = data->bio;
720
0
            else if ((current_out = allocated_out = BIO_new(BIO_s_mem()))
721
0
                     == NULL)
722
0
                ok = 0;     /* Assume BIO_new() recorded an error */
723
724
0
            if (ok)
725
0
                ok = (cbio = ossl_core_bio_new_from_bio(current_out)) != NULL;
726
0
            if (ok) {
727
0
                ok = current_encoder->encode(current_encoder_ctx, cbio,
728
0
                                             original_data, current_abstract,
729
0
                                             data->ctx->selection,
730
0
                                             ossl_pw_passphrase_callback_enc,
731
0
                                             &data->ctx->pwdata);
732
0
                OSSL_TRACE_BEGIN(ENCODER) {
733
0
                    BIO_printf(trc_out,
734
0
                               "[%d] (ctx %p) Running encoder instance %p => %d\n",
735
0
                               data->level, (void *)data->ctx,
736
0
                               (void *)current_encoder_inst, ok);
737
0
                } OSSL_TRACE_END(ENCODER);
738
0
            }
739
740
0
            ossl_core_bio_free(cbio);
741
0
            data->prev_encoder_inst = current_encoder_inst;
742
0
        }
743
0
    }
744
745
    /* Cleanup and collecting the result */
746
747
0
    OPENSSL_free(data->running_output);
748
0
    data->running_output = NULL;
749
750
    /*
751
     * Steal the output from the BIO_s_mem, if we did allocate one.
752
     * That'll be the data for an object abstraction in the next round.
753
     */
754
0
    if (allocated_out != NULL) {
755
0
        BUF_MEM *buf;
756
757
0
        BIO_get_mem_ptr(allocated_out, &buf);
758
0
        data->running_output = (unsigned char *)buf->data;
759
0
        data->running_output_length = buf->length;
760
0
        memset(buf, 0, sizeof(*buf));
761
0
    }
762
763
0
    BIO_free(allocated_out);
764
0
    if (original_data != NULL)
765
0
        data->ctx->cleanup(data->ctx->construct_data);
766
0
    return ok;
767
0
}
768
769
int ossl_bio_print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn)
770
0
{
771
0
    int ret = 0, use_sep = 0;
772
0
    char *hex_str = NULL, *p;
773
0
    const char spaces[] = "    ";
774
0
    const char *post_label_spc = " ";
775
776
0
    const char *neg = "";
777
0
    int bytes;
778
779
0
    if (bn == NULL)
780
0
        return 0;
781
0
    if (label == NULL) {
782
0
        label = "";
783
0
        post_label_spc = "";
784
0
    }
785
786
0
    if (BN_is_zero(bn))
787
0
        return BIO_printf(out, "%s%s0\n", label, post_label_spc);
788
789
0
    if (BN_num_bytes(bn) <= BN_BYTES) {
790
0
        BN_ULONG *words = bn_get_words(bn);
791
792
0
        if (BN_is_negative(bn))
793
0
            neg = "-";
794
795
0
        return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n",
796
0
                          label, post_label_spc, neg, words[0], neg, words[0]);
797
0
    }
798
799
0
    hex_str = BN_bn2hex(bn);
800
0
    if (hex_str == NULL)
801
0
        return 0;
802
803
0
    p = hex_str;
804
0
    if (*p == '-') {
805
0
        ++p;
806
0
        neg = " (Negative)";
807
0
    }
808
0
    if (BIO_printf(out, "%s%s\n", label, neg) <= 0)
809
0
        goto err;
810
811
    /* Keep track of how many bytes we have printed out so far */
812
0
    bytes = 0;
813
814
0
    if (BIO_printf(out, "%s", spaces) <= 0)
815
0
        goto err;
816
817
    /* Add a leading 00 if the top bit is set */
818
0
    if (*p >= '8') {
819
0
        if (BIO_printf(out, "%02x", 0) <= 0)
820
0
            goto err;
821
0
        ++bytes;
822
0
        use_sep = 1;
823
0
    }
824
0
    while (*p != '\0') {
825
        /* Do a newline after every 15 hex bytes + add the space indent */
826
0
        if ((bytes % 15) == 0 && bytes > 0) {
827
0
            if (BIO_printf(out, ":\n%s", spaces) <= 0)
828
0
                goto err;
829
0
            use_sep = 0; /* The first byte on the next line doesn't have a : */
830
0
        }
831
0
        if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "",
832
0
                       tolower((unsigned char)p[0]),
833
0
                       tolower((unsigned char)p[1])) <= 0)
834
0
            goto err;
835
0
        ++bytes;
836
0
        p += 2;
837
0
        use_sep = 1;
838
0
    }
839
0
    if (BIO_printf(out, "\n") <= 0)
840
0
        goto err;
841
0
    ret = 1;
842
0
err:
843
0
    OPENSSL_free(hex_str);
844
0
    return ret;
845
0
}
846
847
int ossl_bio_print_labeled_buf(BIO *out, const char *label,
848
                           const unsigned char *buf, size_t buflen)
849
0
{
850
0
    size_t i;
851
852
0
    if (BIO_printf(out, "%s\n", label) <= 0)
853
0
        return 0;
854
855
0
    for (i = 0; i < buflen; i++) {
856
0
        if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
857
0
            if (i > 0 && BIO_printf(out, "\n") <= 0)
858
0
                return 0;
859
0
            if (BIO_printf(out, "    ") <= 0)
860
0
                return 0;
861
0
        }
862
863
0
        if (BIO_printf(out, "%02x%s", buf[i],
864
0
                                 (i == buflen - 1) ? "" : ":") <= 0)
865
0
            return 0;
866
0
    }
867
0
    if (BIO_printf(out, "\n") <= 0)
868
0
        return 0;
869
870
0
    return 1;
871
0
}
872
873
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA)
874
int ossl_bio_print_ffc_params(BIO *out, const FFC_PARAMS *ffc)
875
0
{
876
0
    if (ffc->nid != NID_undef) {
877
0
#ifndef OPENSSL_NO_DH
878
0
        const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
879
0
        const char *name = ossl_ffc_named_group_get_name(group);
880
881
0
        if (name == NULL)
882
0
            goto err;
883
0
        if (BIO_printf(out, "GROUP: %s\n", name) <= 0)
884
0
            goto err;
885
0
        return 1;
886
#else
887
        /* How could this be? We should not have a nid in a no-dh build. */
888
        goto err;
889
#endif
890
0
    }
891
892
0
    if (!ossl_bio_print_labeled_bignum(out, "P:   ", ffc->p))
893
0
        goto err;
894
0
    if (ffc->q != NULL) {
895
0
        if (!ossl_bio_print_labeled_bignum(out, "Q:   ", ffc->q))
896
0
            goto err;
897
0
    }
898
0
    if (!ossl_bio_print_labeled_bignum(out, "G:   ", ffc->g))
899
0
        goto err;
900
0
    if (ffc->j != NULL) {
901
0
        if (!ossl_bio_print_labeled_bignum(out, "J:   ", ffc->j))
902
0
            goto err;
903
0
    }
904
0
    if (ffc->seed != NULL) {
905
0
        if (!ossl_bio_print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen))
906
0
            goto err;
907
0
    }
908
0
    if (ffc->gindex != -1) {
909
0
        if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0)
910
0
            goto err;
911
0
    }
912
0
    if (ffc->pcounter != -1) {
913
0
        if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0)
914
0
            goto err;
915
0
    }
916
0
    if (ffc->h != 0) {
917
0
        if (BIO_printf(out, "h: %d\n", ffc->h) <= 0)
918
0
            goto err;
919
0
    }
920
0
    return 1;
921
0
err:
922
0
    return 0;
923
0
}
924
925
#endif