Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/encode_decode/decoder_meth.c
Line
Count
Source
1
/*
2
 * Copyright 2020-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 <openssl/core.h>
11
#include <openssl/core_dispatch.h>
12
#include <openssl/decoder.h>
13
#include <openssl/ui.h>
14
#include "internal/core.h"
15
#include "internal/namemap.h"
16
#include "internal/property.h"
17
#include "internal/provider.h"
18
#include "crypto/decoder.h"
19
#include "encoder_local.h"
20
#include "crypto/context.h"
21
22
/*
23
 * Decoder can have multiple names, separated with colons in a name string
24
 */
25
0
#define NAME_SEPARATOR ':'
26
27
static void ossl_decoder_free(void *data)
28
0
{
29
0
    OSSL_DECODER *decoder = (OSSL_DECODER *)data;
30
0
    int ref = 0;
31
32
0
    if (decoder == NULL)
33
0
        return;
34
35
0
    CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref);
36
0
    if (ref > 0)
37
0
        return;
38
0
    OPENSSL_free(decoder->base.name);
39
0
    ossl_property_free(decoder->base.parsed_propdef);
40
0
    ossl_provider_free(decoder->base.prov);
41
0
    CRYPTO_FREE_REF(&decoder->base.refcnt);
42
0
    OPENSSL_free(decoder);
43
0
}
44
45
static int ossl_decoder_up_ref(void *data)
46
0
{
47
0
    OSSL_DECODER *decoder = (OSSL_DECODER *)data;
48
0
    int ref = 0;
49
50
0
    CRYPTO_UP_REF(&decoder->base.refcnt, &ref);
51
0
    return 1;
52
0
}
53
54
/* Simple method structure constructor and destructor */
55
static OSSL_DECODER *ossl_decoder_new(void)
56
0
{
57
0
    OSSL_DECODER *decoder = NULL;
58
59
0
    if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL)
60
0
        return NULL;
61
0
    if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) {
62
0
        ossl_decoder_free(decoder);
63
0
        return NULL;
64
0
    }
65
66
0
    return decoder;
67
0
}
68
69
int OSSL_DECODER_up_ref(OSSL_DECODER *decoder)
70
0
{
71
#ifdef OPENSSL_NO_CACHED_FETCH
72
    return ossl_decoder_up_ref(decoder);
73
#else
74
    /*
75
     * DECODERS do something weird.  They manually build methods rather than
76
     * attempt to fetch them from the method store or construct them through
77
     * the ossl_generic_fetch mechanism.  As such they don't make use of the refcounting
78
     * that we rely on in the method store, and so we always need to refcount them here
79
     * We can identify them based on the fact that they never have a registered nid (i.e.
80
     * its always zero)
81
     */
82
0
    if (decoder->base.id == 0 || decoder->base.no_store != 0)
83
0
        return ossl_decoder_up_ref(decoder);
84
0
    return 1;
85
0
#endif
86
0
}
87
88
void OSSL_DECODER_free(OSSL_DECODER *decoder)
89
0
{
90
#ifdef OPENSSL_NO_CACHED_FETCH
91
    ossl_decoder_free(decoder);
92
#else
93
0
    if (decoder != NULL && (decoder->base.id == 0 || decoder->base.no_store != 0))
94
0
        ossl_decoder_free(decoder);
95
0
#endif
96
0
}
97
98
/* Data to be passed through ossl_method_construct() */
99
struct decoder_data_st {
100
    OSSL_LIB_CTX *libctx;
101
    int id; /* For get_decoder_from_store() */
102
    const char *names; /* For get_decoder_from_store() */
103
    const char *propquery; /* For get_decoder_from_store() */
104
105
    OSSL_METHOD_STORE *tmp_store; /* For get_tmp_decoder_store() */
106
107
    unsigned int flag_construct_error_occurred : 1;
108
};
109
110
/*
111
 * Generic routines to fetch / create DECODER methods with
112
 * ossl_method_construct()
113
 */
114
115
/* Temporary decoder method store, constructor and destructor */
116
static void *get_tmp_decoder_store(void *data)
117
0
{
118
0
    struct decoder_data_st *methdata = data;
119
120
0
    if (methdata->tmp_store == NULL)
121
0
        methdata->tmp_store = ossl_method_store_new(methdata->libctx);
122
0
    return methdata->tmp_store;
123
0
}
124
125
static void dealloc_tmp_decoder_store(void *store)
126
0
{
127
0
    if (store != NULL)
128
0
        ossl_method_store_free(store);
129
0
}
130
131
/* Get the permanent decoder store */
132
static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx)
133
12
{
134
12
    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX);
135
12
}
136
137
static int reserve_decoder_store(void *store, void *data)
138
0
{
139
0
    struct decoder_data_st *methdata = data;
140
141
0
    if (store == NULL
142
0
        && (store = get_decoder_store(methdata->libctx)) == NULL)
143
0
        return 0;
144
145
0
    return ossl_method_lock_store(store);
146
0
}
147
148
static int unreserve_decoder_store(void *store, void *data)
149
0
{
150
0
    struct decoder_data_st *methdata = data;
151
152
0
    if (store == NULL
153
0
        && (store = get_decoder_store(methdata->libctx)) == NULL)
154
0
        return 0;
155
156
0
    return ossl_method_unlock_store(store);
157
0
}
158
159
/* Get decoder methods from a store, or put one in */
160
static void *get_decoder_from_store(void *store, const OSSL_PROVIDER **prov,
161
    void *data)
162
0
{
163
0
    struct decoder_data_st *methdata = data;
164
0
    void *method = NULL;
165
0
    int id;
166
167
    /*
168
     * get_decoder_from_store() is only called to try and get the method
169
     * that OSSL_DECODER_fetch() is asking for, and the name or name id are
170
     * passed via methdata.
171
     */
172
0
    if ((id = methdata->id) == 0 && methdata->names != NULL) {
173
0
        OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
174
0
        const char *names = methdata->names;
175
0
        const char *q = strchr(names, NAME_SEPARATOR);
176
0
        size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
177
178
0
        if (namemap == 0)
179
0
            return NULL;
180
0
        id = ossl_namemap_name2num_n(namemap, names, l);
181
0
    }
182
183
0
    if (id == 0)
184
0
        return NULL;
185
186
0
    if (store == NULL
187
0
        && (store = get_decoder_store(methdata->libctx)) == NULL)
188
0
        return NULL;
189
190
0
    if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
191
0
        return NULL;
192
0
    return method;
193
0
}
194
195
static int put_decoder_in_store(void *store, void *method,
196
    const OSSL_PROVIDER *prov,
197
    const char *names, const char *propdef,
198
    void *data)
199
0
{
200
0
    struct decoder_data_st *methdata = data;
201
0
    OSSL_NAMEMAP *namemap;
202
0
    int id;
203
0
    size_t l = 0;
204
205
    /*
206
     * put_decoder_in_store() is only called with an OSSL_DECODER method that
207
     * was successfully created by construct_decoder() below, which means that
208
     * all the names should already be stored in the namemap with the same
209
     * numeric identity, so just use the first to get that identity.
210
     */
211
0
    if (names != NULL) {
212
0
        const char *q = strchr(names, NAME_SEPARATOR);
213
214
0
        l = (q == NULL ? strlen(names) : (size_t)(q - names));
215
0
    }
216
217
0
    if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
218
0
        || (id = ossl_namemap_name2num_n(namemap, names, l)) == 0)
219
0
        return 0;
220
221
0
    if (store == NULL && (store = get_decoder_store(methdata->libctx)) == NULL)
222
0
        return 0;
223
224
0
    return ossl_method_store_add(store, prov, id, propdef, method,
225
0
        ossl_decoder_up_ref,
226
0
        ossl_decoder_free);
227
0
}
228
229
/* Create and populate a decoder method */
230
void *ossl_decoder_from_algorithm(int id, const OSSL_ALGORITHM *algodef,
231
    OSSL_PROVIDER *prov, int no_store)
232
0
{
233
0
    OSSL_DECODER *decoder = NULL;
234
0
    const OSSL_DISPATCH *fns = algodef->implementation;
235
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
236
237
0
    if ((decoder = ossl_decoder_new()) == NULL)
238
0
        return NULL;
239
0
    decoder->base.id = id;
240
0
    decoder->base.no_store = no_store;
241
0
    if ((decoder->base.name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
242
0
        ossl_decoder_free(decoder);
243
0
        return NULL;
244
0
    }
245
0
    decoder->base.algodef = algodef;
246
0
    if ((decoder->base.parsed_propdef
247
0
            = ossl_parse_property(libctx, algodef->property_definition))
248
0
        == NULL) {
249
0
        ossl_decoder_free(decoder);
250
0
        return NULL;
251
0
    }
252
253
0
    for (; fns->function_id != 0; fns++) {
254
0
        switch (fns->function_id) {
255
0
        case OSSL_FUNC_DECODER_NEWCTX:
256
0
            if (decoder->newctx == NULL)
257
0
                decoder->newctx = OSSL_FUNC_decoder_newctx(fns);
258
0
            break;
259
0
        case OSSL_FUNC_DECODER_FREECTX:
260
0
            if (decoder->freectx == NULL)
261
0
                decoder->freectx = OSSL_FUNC_decoder_freectx(fns);
262
0
            break;
263
0
        case OSSL_FUNC_DECODER_GET_PARAMS:
264
0
            if (decoder->get_params == NULL)
265
0
                decoder->get_params = OSSL_FUNC_decoder_get_params(fns);
266
0
            break;
267
0
        case OSSL_FUNC_DECODER_GETTABLE_PARAMS:
268
0
            if (decoder->gettable_params == NULL)
269
0
                decoder->gettable_params = OSSL_FUNC_decoder_gettable_params(fns);
270
0
            break;
271
0
        case OSSL_FUNC_DECODER_SET_CTX_PARAMS:
272
0
            if (decoder->set_ctx_params == NULL)
273
0
                decoder->set_ctx_params = OSSL_FUNC_decoder_set_ctx_params(fns);
274
0
            break;
275
0
        case OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS:
276
0
            if (decoder->settable_ctx_params == NULL)
277
0
                decoder->settable_ctx_params = OSSL_FUNC_decoder_settable_ctx_params(fns);
278
0
            break;
279
0
        case OSSL_FUNC_DECODER_DOES_SELECTION:
280
0
            if (decoder->does_selection == NULL)
281
0
                decoder->does_selection = OSSL_FUNC_decoder_does_selection(fns);
282
0
            break;
283
0
        case OSSL_FUNC_DECODER_DECODE:
284
0
            if (decoder->decode == NULL)
285
0
                decoder->decode = OSSL_FUNC_decoder_decode(fns);
286
0
            break;
287
0
        case OSSL_FUNC_DECODER_EXPORT_OBJECT:
288
0
            if (decoder->export_object == NULL)
289
0
                decoder->export_object = OSSL_FUNC_decoder_export_object(fns);
290
0
            break;
291
0
        }
292
0
    }
293
    /*
294
     * Try to check that the method is sensible.
295
     * If you have a constructor, you must have a destructor and vice versa.
296
     * You must have at least one of the encoding driver functions.
297
     */
298
0
    if (!((decoder->newctx == NULL && decoder->freectx == NULL)
299
0
            || (decoder->newctx != NULL && decoder->freectx != NULL))
300
0
        || decoder->decode == NULL) {
301
0
        ossl_decoder_free(decoder);
302
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROVIDER_FUNCTIONS);
303
0
        return NULL;
304
0
    }
305
306
0
    if (prov != NULL && !ossl_provider_up_ref(prov)) {
307
0
        ossl_decoder_free(decoder);
308
0
        return NULL;
309
0
    }
310
311
0
    decoder->base.prov = prov;
312
0
    return decoder;
313
0
}
314
315
/*
316
 * The core fetching functionality passes the names of the implementation.
317
 * This function is responsible to getting an identity number for them,
318
 * then call ossl_decoder_from_algorithm() with that identity number.
319
 */
320
static void *construct_decoder(const OSSL_ALGORITHM *algodef,
321
    OSSL_PROVIDER *prov, void *data, int no_store)
322
0
{
323
    /*
324
     * This function is only called if get_decoder_from_store() returned
325
     * NULL, so it's safe to say that of all the spots to create a new
326
     * namemap entry, this is it.  Should the name already exist there, we
327
     * know that ossl_namemap_add() will return its corresponding number.
328
     */
329
0
    struct decoder_data_st *methdata = data;
330
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
331
0
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
332
0
    const char *names = algodef->algorithm_names;
333
0
    int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
334
0
    void *method = NULL;
335
336
0
    if (id != 0)
337
0
        method = ossl_decoder_from_algorithm(id, algodef, prov, no_store);
338
339
    /*
340
     * Flag to indicate that there was actual construction errors.  This
341
     * helps inner_evp_generic_fetch() determine what error it should
342
     * record on inaccessible algorithms.
343
     */
344
0
    if (method == NULL)
345
0
        methdata->flag_construct_error_occurred = 1;
346
347
0
    return method;
348
0
}
349
350
/* Intermediary function to avoid ugly casts, used below */
351
static void destruct_decoder(void *method, void *data)
352
0
{
353
0
    ossl_decoder_free(method);
354
0
}
355
356
/* Fetching support.  Can fetch by numeric identity or by name */
357
static OSSL_DECODER *
358
inner_ossl_decoder_fetch(struct decoder_data_st *methdata,
359
    const char *name, const char *properties)
360
0
{
361
0
    OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx);
362
0
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
363
0
    const char *const propq = properties != NULL ? properties : "";
364
0
    void *method = NULL;
365
0
    int unsupported, id;
366
367
0
    if (store == NULL || namemap == NULL) {
368
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT);
369
0
        return NULL;
370
0
    }
371
372
0
    id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0;
373
374
    /*
375
     * If we haven't found the name yet, chances are that the algorithm to
376
     * be fetched is unsupported.
377
     */
378
0
    unsupported = id == 0;
379
380
0
    if (id == 0
381
0
        || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
382
0
        OSSL_METHOD_CONSTRUCT_METHOD mcm = {
383
0
            get_tmp_decoder_store,
384
0
            reserve_decoder_store,
385
0
            unreserve_decoder_store,
386
0
            get_decoder_from_store,
387
0
            put_decoder_in_store,
388
0
            construct_decoder,
389
0
            destruct_decoder
390
0
        };
391
0
        OSSL_PROVIDER *prov = NULL;
392
393
0
        methdata->id = id;
394
0
        methdata->names = name;
395
0
        methdata->propquery = propq;
396
0
        methdata->flag_construct_error_occurred = 0;
397
0
        if ((method = ossl_method_construct(methdata->libctx, OSSL_OP_DECODER,
398
0
                 &prov, 0 /* !force_cache */,
399
0
                 &mcm, methdata))
400
0
            != NULL) {
401
            /*
402
             * If construction did create a method for us, we know that
403
             * there is a correct name_id and meth_id, since those have
404
             * already been calculated in get_decoder_from_store() and
405
             * put_decoder_in_store() above.
406
             */
407
0
            if (id == 0 && name != NULL)
408
0
                id = ossl_namemap_name2num(namemap, name);
409
0
            if (id != 0 && methdata->tmp_store == NULL) {
410
0
                ossl_method_store_cache_set(store, prov, id, propq, method,
411
0
                    ossl_decoder_up_ref, ossl_decoder_free);
412
0
            } else {
413
                /*
414
                 * Like with EVP methods, if the provider requests no caching we need
415
                 * to take an extra refcount here so that the tmp_stored decoder
416
                 * lives beyond the freeing of that tmp_store
417
                 */
418
0
#ifndef OPENSSL_NO_CACHED_FETCH
419
0
                OSSL_DECODER_up_ref((OSSL_DECODER *)method);
420
0
#endif
421
0
            }
422
0
        }
423
424
        /*
425
         * If we never were in the constructor, the algorithm to be fetched
426
         * is unsupported.
427
         */
428
0
        unsupported = !methdata->flag_construct_error_occurred;
429
0
    }
430
431
0
    if ((id != 0 || name != NULL) && method == NULL) {
432
0
        int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
433
434
0
        if (name == NULL)
435
0
            name = ossl_namemap_num2name(namemap, id, 0);
436
0
        ERR_raise_data(ERR_LIB_OSSL_DECODER, code,
437
0
            "%s, Name (%s : %d), Properties (%s)",
438
0
            ossl_lib_ctx_get_descriptor(methdata->libctx),
439
0
            name == NULL ? "<null>" : name, id,
440
0
            properties == NULL ? "<null>" : properties);
441
0
    }
442
443
0
    return method;
444
0
}
445
446
OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
447
    const char *properties)
448
0
{
449
0
    struct decoder_data_st methdata;
450
0
    void *method;
451
452
0
    methdata.libctx = libctx;
453
0
    methdata.tmp_store = NULL;
454
0
    method = inner_ossl_decoder_fetch(&methdata, name, properties);
455
0
    dealloc_tmp_decoder_store(methdata.tmp_store);
456
0
    return method;
457
0
}
458
459
int ossl_decoder_store_cache_flush(OSSL_LIB_CTX *libctx)
460
12
{
461
12
    OSSL_METHOD_STORE *store = get_decoder_store(libctx);
462
463
12
    if (store != NULL)
464
12
        return ossl_method_store_cache_flush_all(store);
465
0
    return 1;
466
12
}
467
468
int ossl_decoder_store_remove_all_provided(const OSSL_PROVIDER *prov)
469
0
{
470
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
471
0
    OSSL_METHOD_STORE *store = get_decoder_store(libctx);
472
473
0
    if (store != NULL)
474
0
        return ossl_method_store_remove_all_provided(store, prov);
475
0
    return 1;
476
0
}
477
478
/*
479
 * Library of basic method functions
480
 */
481
482
const OSSL_PROVIDER *OSSL_DECODER_get0_provider(const OSSL_DECODER *decoder)
483
0
{
484
0
    if (!ossl_assert(decoder != NULL)) {
485
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
486
0
        return 0;
487
0
    }
488
489
0
    return decoder->base.prov;
490
0
}
491
492
const char *OSSL_DECODER_get0_properties(const OSSL_DECODER *decoder)
493
0
{
494
0
    if (!ossl_assert(decoder != NULL)) {
495
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
496
0
        return 0;
497
0
    }
498
499
0
    return decoder->base.algodef->property_definition;
500
0
}
501
502
const OSSL_PROPERTY_LIST *
503
ossl_decoder_parsed_properties(const OSSL_DECODER *decoder)
504
0
{
505
0
    if (!ossl_assert(decoder != NULL)) {
506
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
507
0
        return 0;
508
0
    }
509
510
0
    return decoder->base.parsed_propdef;
511
0
}
512
513
int ossl_decoder_get_number(const OSSL_DECODER *decoder)
514
0
{
515
0
    if (!ossl_assert(decoder != NULL)) {
516
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
517
0
        return 0;
518
0
    }
519
520
0
    return decoder->base.id;
521
0
}
522
523
const char *OSSL_DECODER_get0_name(const OSSL_DECODER *decoder)
524
0
{
525
0
    return decoder->base.name;
526
0
}
527
528
const char *OSSL_DECODER_get0_description(const OSSL_DECODER *decoder)
529
0
{
530
0
    return decoder->base.algodef->algorithm_description;
531
0
}
532
533
int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name)
534
0
{
535
0
    if (decoder->base.prov != NULL) {
536
0
        OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
537
0
        OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
538
539
0
        return ossl_namemap_name2num(namemap, name) == decoder->base.id;
540
0
    }
541
0
    return 0;
542
0
}
543
544
static int resolve_name(OSSL_DECODER *decoder, const char *name)
545
0
{
546
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
547
0
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
548
549
0
    return ossl_namemap_name2num(namemap, name);
550
0
}
551
552
int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, const char *name, int *id_cache)
553
0
{
554
0
    int id = *id_cache;
555
556
0
    if (id <= 0)
557
0
        *id_cache = id = resolve_name(decoder, name);
558
559
0
    return id > 0 && ossl_decoder_get_number(decoder) == id;
560
0
}
561
562
struct do_one_data_st {
563
    void (*user_fn)(OSSL_DECODER *decoder, void *arg);
564
    void *user_arg;
565
};
566
567
static void do_one(ossl_unused int id, void *method, void *arg)
568
0
{
569
0
    struct do_one_data_st *data = arg;
570
571
0
    data->user_fn(method, data->user_arg);
572
0
}
573
574
void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
575
    void (*user_fn)(OSSL_DECODER *decoder,
576
        void *arg),
577
    void *user_arg)
578
0
{
579
0
    struct decoder_data_st methdata;
580
0
    struct do_one_data_st data;
581
582
0
    methdata.libctx = libctx;
583
0
    methdata.tmp_store = NULL;
584
0
    (void)inner_ossl_decoder_fetch(&methdata, NULL, NULL /* properties */);
585
586
0
    data.user_fn = user_fn;
587
0
    data.user_arg = user_arg;
588
0
    if (methdata.tmp_store != NULL)
589
0
        ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
590
0
    ossl_method_store_do_all(get_decoder_store(libctx), &do_one, &data);
591
0
    dealloc_tmp_decoder_store(methdata.tmp_store);
592
0
}
593
594
int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder,
595
    void (*fn)(const char *name, void *data),
596
    void *data)
597
0
{
598
0
    if (decoder == NULL)
599
0
        return 0;
600
601
0
    if (decoder->base.prov != NULL) {
602
0
        OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
603
0
        OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
604
605
0
        return ossl_namemap_doall_names(namemap, decoder->base.id, fn, data);
606
0
    }
607
608
0
    return 1;
609
0
}
610
611
const OSSL_PARAM *
612
OSSL_DECODER_gettable_params(OSSL_DECODER *decoder)
613
0
{
614
0
    if (decoder != NULL && decoder->gettable_params != NULL) {
615
0
        void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder));
616
617
0
        return decoder->gettable_params(provctx);
618
0
    }
619
0
    return NULL;
620
0
}
621
622
int OSSL_DECODER_get_params(OSSL_DECODER *decoder, OSSL_PARAM params[])
623
0
{
624
0
    if (decoder != NULL && decoder->get_params != NULL)
625
0
        return decoder->get_params(params);
626
0
    return 0;
627
0
}
628
629
const OSSL_PARAM *
630
OSSL_DECODER_settable_ctx_params(OSSL_DECODER *decoder)
631
0
{
632
0
    if (decoder != NULL && decoder->settable_ctx_params != NULL) {
633
0
        void *provctx = ossl_provider_ctx(OSSL_DECODER_get0_provider(decoder));
634
635
0
        return decoder->settable_ctx_params(provctx);
636
0
    }
637
0
    return NULL;
638
0
}
639
640
/*
641
 * Decoder context support
642
 */
643
644
/*
645
 * |encoder| value NULL is valid, and signifies that there is no decoder.
646
 * This is useful to provide fallback mechanisms.
647
 *  Functions that want to verify if there is a decoder can do so with
648
 * OSSL_DECODER_CTX_get_decoder()
649
 */
650
OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void)
651
0
{
652
0
    OSSL_DECODER_CTX *ctx;
653
654
0
    ctx = OPENSSL_zalloc(sizeof(*ctx));
655
0
    return ctx;
656
0
}
657
658
int OSSL_DECODER_CTX_set_params(OSSL_DECODER_CTX *ctx,
659
    const OSSL_PARAM params[])
660
0
{
661
0
    int ok = 1;
662
0
    int i;
663
0
    int l;
664
665
0
    if (!ossl_assert(ctx != NULL)) {
666
0
        ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER);
667
0
        return 0;
668
0
    }
669
670
0
    if (ctx->decoder_insts == NULL)
671
0
        return 1;
672
673
0
    l = OSSL_DECODER_CTX_get_num_decoders(ctx);
674
0
    for (i = 0; i < l; i++) {
675
0
        OSSL_DECODER_INSTANCE *decoder_inst = sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i);
676
0
        OSSL_DECODER *decoder = OSSL_DECODER_INSTANCE_get_decoder(decoder_inst);
677
0
        OSSL_DECODER *decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(decoder_inst);
678
679
0
        if (decoderctx == NULL || decoder->set_ctx_params == NULL)
680
0
            continue;
681
0
        if (!decoder->set_ctx_params(decoderctx, params))
682
0
            ok = 0;
683
0
    }
684
0
    return ok;
685
0
}
686
687
void OSSL_DECODER_CTX_free(OSSL_DECODER_CTX *ctx)
688
0
{
689
0
    if (ctx != NULL) {
690
0
        if (ctx->cleanup != NULL)
691
0
            ctx->cleanup(ctx->construct_data);
692
0
        sk_OSSL_DECODER_INSTANCE_pop_free(ctx->decoder_insts,
693
0
            ossl_decoder_instance_free);
694
0
        ossl_pw_clear_passphrase_data(&ctx->pwdata);
695
0
        OPENSSL_free(ctx);
696
0
    }
697
0
}