Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/evp/evp_fetch.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 <stddef.h>
11
#include <openssl/types.h>
12
#include <openssl/evp.h>
13
#include <openssl/core.h>
14
#include <openssl/kdf.h>
15
#include "internal/cryptlib.h"
16
#include "internal/thread_once.h"
17
#include "internal/property.h"
18
#include "internal/core.h"
19
#include "internal/provider.h"
20
#include "internal/namemap.h"
21
#include "crypto/decoder.h"
22
#include "crypto/evp.h" /* evp_local.h needs it */
23
#include "evp_local.h"
24
25
1.58k
#define NAME_SEPARATOR ':'
26
27
/* Data to be passed through ossl_method_construct() */
28
struct evp_method_data_st {
29
    OSSL_LIB_CTX *libctx;
30
    int operation_id; /* For get_evp_method_from_store() */
31
    int name_id; /* For get_evp_method_from_store() */
32
    const char *names; /* For get_evp_method_from_store() */
33
    const char *propquery; /* For get_evp_method_from_store() */
34
35
    OSSL_METHOD_STORE *tmp_store; /* For get_tmp_evp_method_store() */
36
37
    unsigned int flag_construct_error_occurred : 1;
38
39
    void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *,
40
        OSSL_PROVIDER *, int);
41
    int (*refcnt_up_method)(void *method);
42
    void (*destruct_method)(void *method);
43
};
44
45
/*
46
 * Generic routines to fetch / create EVP methods with ossl_method_construct()
47
 */
48
static void *get_tmp_evp_method_store(void *data)
49
0
{
50
0
    struct evp_method_data_st *methdata = data;
51
52
0
    if (methdata->tmp_store == NULL) {
53
0
        methdata->tmp_store = ossl_method_store_new(methdata->libctx);
54
0
        OSSL_TRACE1(QUERY, "Allocating a new tmp_store %p\n", (void *)methdata->tmp_store);
55
0
    } else {
56
0
        OSSL_TRACE1(QUERY, "Using the existing tmp_store %p\n", (void *)methdata->tmp_store);
57
0
    }
58
0
    return methdata->tmp_store;
59
0
}
60
61
static void dealloc_tmp_evp_method_store(void *store)
62
795k
{
63
795k
    OSSL_TRACE1(QUERY, "Deallocating the tmp_store %p\n", store);
64
795k
    if (store != NULL)
65
0
        ossl_method_store_free(store);
66
795k
}
67
68
static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx)
69
800k
{
70
800k
    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX);
71
800k
}
72
73
static int reserve_evp_method_store(void *store, void *data)
74
2.27k
{
75
2.27k
    struct evp_method_data_st *methdata = data;
76
77
2.27k
    if (store == NULL
78
2.27k
        && (store = get_evp_method_store(methdata->libctx)) == NULL)
79
0
        return 0;
80
81
2.27k
    return ossl_method_lock_store(store);
82
2.27k
}
83
84
static int unreserve_evp_method_store(void *store, void *data)
85
2.27k
{
86
2.27k
    struct evp_method_data_st *methdata = data;
87
88
2.27k
    if (store == NULL
89
2.27k
        && (store = get_evp_method_store(methdata->libctx)) == NULL)
90
0
        return 0;
91
92
2.27k
    return ossl_method_unlock_store(store);
93
2.27k
}
94
95
/*
96
 * To identify the method in the EVP method store, we mix the name identity
97
 * with the operation identity, under the assumption that we don't have more
98
 * than 2^23 names or more than 2^8 operation types.
99
 *
100
 * The resulting identity is a 31-bit integer, composed like this:
101
 *
102
 * +---------23 bits--------+-8 bits-+
103
 * |      name identity     | op id  |
104
 * +------------------------+--------+
105
 *
106
 * We limit this composite number to 31 bits, thus leaving the top uint32_t
107
 * bit always zero, to avoid negative sign extension when downshifting after
108
 * this number happens to be passed to an int (which happens as soon as it's
109
 * passed to ossl_method_store_cache_set(), and it's in that form that it
110
 * gets passed along to filter_on_operation_id(), defined further down.
111
 */
112
795k
#define METHOD_ID_OPERATION_MASK 0x000000FF
113
#define METHOD_ID_OPERATION_MAX ((1 << 8) - 1)
114
795k
#define METHOD_ID_NAME_MASK 0x7FFFFF00
115
795k
#define METHOD_ID_NAME_OFFSET 8
116
#define METHOD_ID_NAME_MAX ((1 << 23) - 1)
117
static uint32_t evp_method_id(int name_id, unsigned int operation_id)
118
795k
{
119
795k
    if (!ossl_assert(name_id > 0 && name_id <= METHOD_ID_NAME_MAX)
120
795k
        || !ossl_assert(operation_id > 0
121
795k
            && operation_id <= METHOD_ID_OPERATION_MAX))
122
0
        return 0;
123
795k
    return (((name_id << METHOD_ID_NAME_OFFSET) & METHOD_ID_NAME_MASK)
124
795k
        | (operation_id & METHOD_ID_OPERATION_MASK));
125
795k
}
126
127
static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov,
128
    void *data)
129
1.13k
{
130
1.13k
    struct evp_method_data_st *methdata = data;
131
1.13k
    void *method = NULL;
132
1.13k
    int name_id;
133
1.13k
    uint32_t meth_id;
134
135
    /*
136
     * get_evp_method_from_store() is only called to try and get the method
137
     * that evp_generic_fetch() is asking for, and the operation id as well
138
     * as the name or name id are passed via methdata.
139
     */
140
1.13k
    if ((name_id = methdata->name_id) == 0 && methdata->names != NULL) {
141
1.06k
        OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
142
1.06k
        const char *names = methdata->names;
143
1.06k
        const char *q = strchr(names, NAME_SEPARATOR);
144
1.06k
        size_t l = (q == NULL ? strlen(names) : (size_t)(q - names));
145
146
1.06k
        if (namemap == 0)
147
0
            return NULL;
148
1.06k
        name_id = ossl_namemap_name2num_n(namemap, names, l);
149
1.06k
    }
150
151
1.13k
    if (name_id == 0
152
278
        || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
153
860
        return NULL;
154
155
278
    if (store == NULL
156
278
        && (store = get_evp_method_store(methdata->libctx)) == NULL)
157
0
        return NULL;
158
159
278
    if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, prov,
160
278
            &method))
161
22
        return NULL;
162
256
    return method;
163
278
}
164
165
static int put_evp_method_in_store(void *store, void *method,
166
    const OSSL_PROVIDER *prov,
167
    const char *names, const char *propdef,
168
    void *data)
169
260
{
170
260
    struct evp_method_data_st *methdata = data;
171
260
    OSSL_NAMEMAP *namemap;
172
260
    int name_id;
173
260
    uint32_t meth_id;
174
260
    size_t l = 0;
175
176
    /*
177
     * put_evp_method_in_store() is only called with an EVP method that was
178
     * successfully created by construct_method() below, which means that
179
     * all the names should already be stored in the namemap with the same
180
     * numeric identity, so just use the first to get that identity.
181
     */
182
260
    if (names != NULL) {
183
260
        const char *q = strchr(names, NAME_SEPARATOR);
184
185
260
        l = (q == NULL ? strlen(names) : (size_t)(q - names));
186
260
    }
187
188
260
    if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL
189
260
        || (name_id = ossl_namemap_name2num_n(namemap, names, l)) == 0
190
260
        || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0)
191
0
        return 0;
192
193
260
    OSSL_TRACE1(QUERY, "put_evp_method_in_store: original store: %p\n", store);
194
260
    if (store == NULL
195
260
        && (store = get_evp_method_store(methdata->libctx)) == NULL)
196
0
        return 0;
197
198
260
    OSSL_TRACE5(QUERY,
199
260
        "put_evp_method_in_store: "
200
260
        "store: %p, names: %s, operation_id %d, method_id: %d, properties: %s\n",
201
260
        store, names, methdata->operation_id, meth_id, propdef ? propdef : "<null>");
202
260
    return ossl_method_store_add(store, prov, meth_id, propdef, method,
203
260
        methdata->refcnt_up_method,
204
260
        methdata->destruct_method);
205
260
}
206
207
/*
208
 * The core fetching functionality passes the name of the implementation.
209
 * This function is responsible to getting an identity number for it.
210
 */
211
static void *construct_evp_method(const OSSL_ALGORITHM *algodef,
212
    OSSL_PROVIDER *prov, void *data, int no_store)
213
260
{
214
    /*
215
     * This function is only called if get_evp_method_from_store() returned
216
     * NULL, so it's safe to say that of all the spots to create a new
217
     * namemap entry, this is it.  Should the name already exist there, we
218
     * know that ossl_namemap_add_name() will return its corresponding
219
     * number.
220
     */
221
260
    struct evp_method_data_st *methdata = data;
222
260
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
223
260
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
224
260
    const char *names = algodef->algorithm_names;
225
260
    int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
226
260
    void *method;
227
228
260
    if (name_id == 0)
229
0
        return NULL;
230
231
260
    method = methdata->method_from_algorithm(name_id, algodef, prov, no_store);
232
233
    /*
234
     * Flag to indicate that there was actual construction errors.  This
235
     * helps inner_evp_generic_fetch() determine what error it should
236
     * record on inaccessible algorithms.
237
     */
238
260
    if (method == NULL)
239
0
        methdata->flag_construct_error_occurred = 1;
240
241
260
    return method;
242
260
}
243
244
static void destruct_evp_method(void *method, void *data)
245
260
{
246
260
    struct evp_method_data_st *methdata = data;
247
248
260
    methdata->destruct_method(method);
249
260
}
250
251
static void *
252
inner_evp_generic_fetch(struct evp_method_data_st *methdata,
253
    OSSL_PROVIDER *prov, int operation_id,
254
    const char *name, ossl_unused const char *properties,
255
    void *(*new_method)(int name_id,
256
        const OSSL_ALGORITHM *algodef,
257
        OSSL_PROVIDER *prov, int no_store),
258
    int (*up_ref_method)(void *),
259
    void (*free_method)(void *))
260
795k
{
261
795k
    OSSL_METHOD_STORE *store = get_evp_method_store(methdata->libctx);
262
795k
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
263
#ifdef FIPS_MODULE
264
    /*
265
     * The FIPS provider has its own internal library context where only it
266
     * is loaded.  Consequently, property queries aren't relevant because
267
     * there is only one fetchable algorithm and it is assumed that the
268
     * FIPS-ness is handled by the using algorithm.
269
     */
270
    const char *const propq = "";
271
#else
272
795k
    const char *const propq = properties != NULL ? properties : "";
273
795k
#endif /* FIPS_MODULE */
274
795k
    uint32_t meth_id = 0;
275
795k
    void *method = NULL;
276
795k
    int unsupported, name_id;
277
278
795k
    if (store == NULL || namemap == NULL) {
279
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
280
0
        return NULL;
281
0
    }
282
283
    /*
284
     * If there's ever an operation_id == 0 passed, we have an internal
285
     * programming error.
286
     */
287
795k
    if (!ossl_assert(operation_id > 0)) {
288
0
        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
289
0
        return NULL;
290
0
    }
291
292
    /* If we haven't received a name id yet, try to get one for the name */
293
795k
    name_id = ossl_namemap_name2num(namemap, name);
294
295
    /*
296
     * If we have a name id, calculate a method id with evp_method_id().
297
     *
298
     * evp_method_id returns 0 if we have too many operations (more than
299
     * about 2^8) or too many names (more than about 2^24).  In that case,
300
     * we can't create any new method.
301
     * For all intents and purposes, this is an internal error.
302
     */
303
795k
    if (name_id != 0 && (meth_id = evp_method_id(name_id, operation_id)) == 0) {
304
0
        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
305
0
        return NULL;
306
0
    }
307
308
    /*
309
     * If we haven't found the name yet, chances are that the algorithm to
310
     * be fetched is unsupported.
311
     */
312
795k
    unsupported = name_id == 0;
313
314
795k
    if (meth_id == 0
315
794k
        || !ossl_method_store_cache_get(store, prov, meth_id, propq, &method)) {
316
1.13k
        OSSL_METHOD_CONSTRUCT_METHOD mcm = {
317
1.13k
            get_tmp_evp_method_store,
318
1.13k
            reserve_evp_method_store,
319
1.13k
            unreserve_evp_method_store,
320
1.13k
            get_evp_method_from_store,
321
1.13k
            put_evp_method_in_store,
322
1.13k
            construct_evp_method,
323
1.13k
            destruct_evp_method
324
1.13k
        };
325
326
1.13k
        methdata->operation_id = operation_id;
327
1.13k
        methdata->name_id = name_id;
328
1.13k
        methdata->names = name;
329
1.13k
        methdata->propquery = propq;
330
1.13k
        methdata->method_from_algorithm = new_method;
331
1.13k
        methdata->refcnt_up_method = up_ref_method;
332
1.13k
        methdata->destruct_method = free_method;
333
1.13k
        methdata->flag_construct_error_occurred = 0;
334
1.13k
        if ((method = ossl_method_construct(methdata->libctx, operation_id,
335
1.13k
                 &prov, 0 /* !force_cache */,
336
1.13k
                 &mcm, methdata))
337
1.13k
            != NULL) {
338
            /*
339
             * If construction did create a method for us, we know that
340
             * there is a correct name_id and meth_id, since those have
341
             * already been calculated in get_evp_method_from_store() and
342
             * put_evp_method_in_store() above.
343
             * Note that there is a corner case here, in which, if a user
344
             * passes a name of the form name1:name2:..., then the construction
345
             * will create a method against all names, but the lookup will fail
346
             * as ossl_namemap_name2num treats the name string as a single name
347
             * rather than introducing new features where in the EVP_<obj>_fetch
348
             * parses the string and queries for each, return an error.
349
             */
350
256
            if (name_id == 0)
351
204
                name_id = ossl_namemap_name2num(namemap, name);
352
256
            if (name_id == 0) {
353
204
                ERR_raise_data(ERR_LIB_EVP, ERR_R_FETCH_FAILED,
354
204
                    "Algorithm %s cannot be found", name != NULL ? name : "<null>");
355
#ifdef OPENSSL_NO_CACHED_FETCH
356
                free_method(method);
357
#endif
358
204
                method = NULL;
359
204
            } else {
360
52
                meth_id = evp_method_id(name_id, operation_id);
361
                /*
362
                 * do not insert method to method store cache when provider
363
                 * did ask for not caching it. methods which are not to be
364
                 * cached end up in ->tmp_store when provider asks not
365
                 * to cache the result (see ossl_method_construct_reserve_store())
366
                 */
367
52
                if (meth_id != 0 && methdata->tmp_store == NULL) {
368
52
                    ossl_method_store_cache_set(store, prov, meth_id, propq,
369
52
                        method, up_ref_method, free_method);
370
52
                } else {
371
0
#ifndef OPENSSL_NO_CACHED_FETCH
372
                    /*
373
                     * There is a corner case we need to handle here.  IF:
374
                     * 1) we are fetching an algorithm and plan to return it to the caller
375
                     * 2) The provider we fetched from requested no_cache
376
                     * Then we are in a situation in which this method that was constructed
377
                     * only lives in the tmp_store, and has a reference count of 1.
378
                     * On return from this function, that tmp_store is going to be deallocated,
379
                     * Which will drop the methods ref count to 0 and free it, after which the
380
                     * method will be returned to the called, as an already freed object.
381
                     *
382
                     * That's bad.  We need to grab an extra ref count on the method before returning
383
                     * so that the requestor via EVP_*_fetch has ownership.
384
                     *
385
                     * BUT we only want to do this in the event that the algorithm is uncached.
386
                     * Unfortunately, we don't know that here, because it was the provider that
387
                     * made that request.  However, each algorithm type does store that information
388
                     * so we have a path forward.  Based on the operation id, call the appropriate
389
                     * up_ref method.  That implementation knows how to query its algorithm type and
390
                     * decide if a reference needs to be taken here
391
                     */
392
0
                    switch (operation_id) {
393
0
                    case OSSL_OP_DIGEST:
394
0
                        EVP_MD_up_ref((EVP_MD *)method);
395
0
                        break;
396
0
                    case OSSL_OP_CIPHER:
397
0
                        EVP_CIPHER_up_ref((EVP_CIPHER *)method);
398
0
                        break;
399
0
                    case OSSL_OP_MAC:
400
0
                        EVP_MAC_up_ref((EVP_MAC *)method);
401
0
                        break;
402
0
                    case OSSL_OP_KDF:
403
0
                        EVP_KDF_up_ref((EVP_KDF *)method);
404
0
                        break;
405
0
                    case OSSL_OP_RAND:
406
0
                        EVP_RAND_up_ref((EVP_RAND *)method);
407
0
                        break;
408
0
                    case OSSL_OP_KEYMGMT:
409
0
                        EVP_KEYMGMT_up_ref((EVP_KEYMGMT *)method);
410
0
                        break;
411
0
                    case OSSL_OP_KEYEXCH:
412
0
                        EVP_KEYEXCH_up_ref((EVP_KEYEXCH *)method);
413
0
                        break;
414
0
                    case OSSL_OP_SIGNATURE:
415
0
                        EVP_SIGNATURE_up_ref((EVP_SIGNATURE *)method);
416
0
                        break;
417
0
                    case OSSL_OP_ASYM_CIPHER:
418
0
                        EVP_ASYM_CIPHER_up_ref((EVP_ASYM_CIPHER *)method);
419
0
                        break;
420
0
                    case OSSL_OP_KEM:
421
0
                        EVP_KEM_up_ref((EVP_KEM *)method);
422
0
                        break;
423
0
                    case OSSL_OP_SKEYMGMT:
424
0
                        EVP_SKEYMGMT_up_ref((EVP_SKEYMGMT *)method);
425
0
                        break;
426
0
                    default:
427
0
                        break;
428
0
                    }
429
0
#endif
430
0
                }
431
52
            }
432
256
        }
433
434
        /*
435
         * If we never were in the constructor, the algorithm to be fetched
436
         * is unsupported.
437
         */
438
1.13k
        unsupported = !methdata->flag_construct_error_occurred;
439
1.13k
    }
440
441
795k
    if ((name_id != 0 || name != NULL) && method == NULL) {
442
1.08k
        int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
443
444
1.08k
        if (name == NULL)
445
0
            name = ossl_namemap_num2name(namemap, name_id, 0);
446
1.08k
        ERR_raise_data(ERR_LIB_EVP, code,
447
1.08k
            "%s, Algorithm (%s : %d), Properties (%s)",
448
1.08k
            ossl_lib_ctx_get_descriptor(methdata->libctx),
449
1.08k
            name == NULL ? "<null>" : name, name_id,
450
1.08k
            properties == NULL ? "<null>" : properties);
451
794k
    } else {
452
794k
        OSSL_TRACE4(QUERY, "%s, Algorithm (%s : %d), Properties (%s)\n",
453
794k
            ossl_lib_ctx_get_descriptor(methdata->libctx),
454
794k
            name == NULL ? "<null>" : name, name_id,
455
794k
            properties == NULL ? "<null>" : properties);
456
794k
    }
457
458
795k
    return method;
459
795k
}
460
461
void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
462
    const char *name, const char *properties,
463
    void *(*new_method)(int name_id,
464
        const OSSL_ALGORITHM *algodef,
465
        OSSL_PROVIDER *prov, int no_store),
466
    int (*up_ref_method)(void *),
467
    void (*free_method)(void *))
468
795k
{
469
795k
    struct evp_method_data_st methdata;
470
795k
    void *method;
471
472
795k
    methdata.libctx = libctx;
473
795k
    methdata.tmp_store = NULL;
474
795k
    method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
475
795k
        name, properties,
476
795k
        new_method, up_ref_method, free_method);
477
795k
    dealloc_tmp_evp_method_store(methdata.tmp_store);
478
795k
    return method;
479
795k
}
480
481
/*
482
 * evp_generic_fetch_from_prov() is special, and only returns methods from
483
 * the given provider.
484
 * This is meant to be used when one method needs to fetch an associated
485
 * method.
486
 */
487
void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
488
    const char *name, const char *properties,
489
    void *(*new_method)(int name_id,
490
        const OSSL_ALGORITHM *algodef,
491
        OSSL_PROVIDER *prov, int no_store),
492
    int (*up_ref_method)(void *),
493
    void (*free_method)(void *))
494
0
{
495
0
    struct evp_method_data_st methdata;
496
0
    void *method;
497
498
0
    methdata.libctx = ossl_provider_libctx(prov);
499
0
    methdata.tmp_store = NULL;
500
0
    method = inner_evp_generic_fetch(&methdata, prov, operation_id,
501
0
        name, properties,
502
0
        new_method, up_ref_method, free_method);
503
0
    dealloc_tmp_evp_method_store(methdata.tmp_store);
504
0
    return method;
505
0
}
506
507
int evp_method_store_cache_flush(OSSL_LIB_CTX *libctx)
508
12
{
509
12
    OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
510
511
12
    if (store != NULL)
512
12
        return ossl_method_store_cache_flush_all(store);
513
0
    return 1;
514
12
}
515
516
int evp_method_store_remove_all_provided(const OSSL_PROVIDER *prov)
517
0
{
518
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
519
0
    OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
520
521
0
    if (store != NULL)
522
0
        return ossl_method_store_remove_all_provided(store, prov);
523
0
    return 1;
524
0
}
525
526
static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
527
    OSSL_PROPERTY_LIST *def_prop,
528
    int loadconfig,
529
    int mirrored)
530
3
{
531
3
    OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
532
3
    OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
533
534
3
    if (plp != NULL && store != NULL) {
535
3
        int ret;
536
3
#ifndef FIPS_MODULE
537
3
        char *propstr = NULL;
538
3
        size_t strsz;
539
540
3
        if (mirrored) {
541
3
            if (ossl_global_properties_no_mirrored(libctx))
542
0
                return 0;
543
3
        } else {
544
            /*
545
             * These properties have been explicitly set on this libctx, so
546
             * don't allow any mirroring from a parent libctx.
547
             */
548
0
            ossl_global_properties_stop_mirroring(libctx);
549
0
        }
550
551
3
        strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0);
552
3
        if (strsz > 0)
553
3
            propstr = OPENSSL_malloc(strsz);
554
3
        if (propstr == NULL) {
555
0
            ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
556
0
            return 0;
557
0
        }
558
3
        if (ossl_property_list_to_string(libctx, def_prop, propstr,
559
3
                strsz)
560
3
            == 0) {
561
0
            OPENSSL_free(propstr);
562
0
            ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
563
0
            return 0;
564
0
        }
565
3
        ossl_provider_default_props_update(libctx, propstr);
566
3
        OPENSSL_free(propstr);
567
3
#endif
568
3
        ossl_property_free(*plp);
569
3
        *plp = def_prop;
570
571
3
        ret = ossl_method_store_cache_flush_all(store);
572
3
#ifndef FIPS_MODULE
573
3
        ossl_decoder_cache_flush(libctx);
574
3
#endif
575
3
        return ret;
576
3
    }
577
3
    ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
578
0
    return 0;
579
3
}
580
581
int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
582
    int loadconfig, int mirrored)
583
3
{
584
3
    OSSL_PROPERTY_LIST *pl = NULL;
585
586
3
    if (propq != NULL && (pl = ossl_parse_query(libctx, propq, 1)) == NULL) {
587
0
        ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
588
0
        return 0;
589
0
    }
590
3
    if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) {
591
0
        ossl_property_free(pl);
592
0
        return 0;
593
0
    }
594
3
    return 1;
595
3
}
596
597
int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
598
0
{
599
0
    return evp_set_default_properties_int(libctx, propq, 1, 0);
600
0
}
601
602
static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq,
603
    int loadconfig)
604
0
{
605
0
    OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
606
0
    OSSL_PROPERTY_LIST *pl1, *pl2;
607
608
0
    if (propq == NULL)
609
0
        return 1;
610
0
    if (plp == NULL || *plp == NULL)
611
0
        return evp_set_default_properties_int(libctx, propq, 0, 0);
612
0
    if ((pl1 = ossl_parse_query(libctx, propq, 1)) == NULL) {
613
0
        ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
614
0
        return 0;
615
0
    }
616
0
    pl2 = ossl_property_merge(pl1, *plp);
617
0
    ossl_property_free(pl1);
618
0
    if (pl2 == NULL) {
619
0
        ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
620
0
        return 0;
621
0
    }
622
0
    if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) {
623
0
        ossl_property_free(pl2);
624
0
        return 0;
625
0
    }
626
0
    return 1;
627
0
}
628
629
static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx,
630
    const char *prop_name)
631
0
{
632
0
    OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1);
633
634
0
    return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp);
635
0
}
636
637
int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx)
638
0
{
639
0
    return evp_default_property_is_enabled(libctx, "fips");
640
0
}
641
642
int evp_default_properties_enable_fips_int(OSSL_LIB_CTX *libctx, int enable,
643
    int loadconfig)
644
0
{
645
0
    const char *query = (enable != 0) ? "fips=yes" : "-fips";
646
647
0
    return evp_default_properties_merge(libctx, query, loadconfig);
648
0
}
649
650
int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable)
651
0
{
652
0
    return evp_default_properties_enable_fips_int(libctx, enable, 1);
653
0
}
654
655
char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig)
656
3
{
657
3
    OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
658
3
    char *propstr = NULL;
659
3
    size_t sz;
660
661
3
    if (plp == NULL)
662
0
        return OPENSSL_strdup("");
663
664
3
    sz = ossl_property_list_to_string(libctx, *plp, NULL, 0);
665
3
    if (sz == 0) {
666
0
        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
667
0
        return NULL;
668
0
    }
669
670
3
    propstr = OPENSSL_malloc(sz);
671
3
    if (propstr == NULL)
672
0
        return NULL;
673
3
    if (ossl_property_list_to_string(libctx, *plp, propstr, sz) == 0) {
674
0
        ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
675
0
        OPENSSL_free(propstr);
676
0
        return NULL;
677
0
    }
678
3
    return propstr;
679
3
}
680
681
char *EVP_get1_default_properties(OSSL_LIB_CTX *libctx)
682
0
{
683
0
    return evp_get_global_properties_str(libctx, ossl_lib_ctx_is_global_default(libctx));
684
0
}
685
686
struct filter_data_st {
687
    int operation_id;
688
    void (*user_fn)(void *method, void *arg);
689
    void *user_arg;
690
};
691
692
static void filter_on_operation_id(int id, void *method, void *arg)
693
0
{
694
0
    struct filter_data_st *data = arg;
695
696
0
    if ((id & METHOD_ID_OPERATION_MASK) == data->operation_id)
697
0
        data->user_fn(method, data->user_arg);
698
0
}
699
700
void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
701
    void (*user_fn)(void *method, void *arg),
702
    void *user_arg,
703
    void *(*new_method)(int name_id,
704
        const OSSL_ALGORITHM *algodef,
705
        OSSL_PROVIDER *prov, int no_store),
706
    int (*up_ref_method)(void *),
707
    void (*free_method)(void *))
708
0
{
709
0
    struct evp_method_data_st methdata;
710
0
    struct filter_data_st data;
711
712
0
    methdata.libctx = libctx;
713
0
    methdata.tmp_store = NULL;
714
0
    (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, NULL, NULL,
715
0
        new_method, up_ref_method, free_method);
716
717
0
    data.operation_id = operation_id;
718
0
    data.user_fn = user_fn;
719
0
    data.user_arg = user_arg;
720
0
    if (methdata.tmp_store != NULL)
721
0
        ossl_method_store_do_all(methdata.tmp_store, &filter_on_operation_id,
722
0
            &data);
723
0
    ossl_method_store_do_all(get_evp_method_store(libctx),
724
0
        &filter_on_operation_id, &data);
725
0
    dealloc_tmp_evp_method_store(methdata.tmp_store);
726
0
}
727
728
int evp_is_a(OSSL_PROVIDER *prov, int number,
729
    const char *legacy_name, const char *name)
730
0
{
731
    /*
732
     * For a |prov| that is NULL, the library context will be NULL
733
     */
734
0
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
735
0
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
736
737
0
    if (prov == NULL)
738
0
        number = ossl_namemap_name2num(namemap, legacy_name);
739
0
    return ossl_namemap_name2num(namemap, name) == number;
740
0
}
741
742
int evp_names_do_all(OSSL_PROVIDER *prov, int number,
743
    void (*fn)(const char *name, void *data),
744
    void *data)
745
260
{
746
260
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
747
260
    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
748
749
260
    return ossl_namemap_doall_names(namemap, number, fn, data);
750
260
}