]>
Commit | Line | Data |
---|---|---|
c13d2ab4 | 1 | /* |
4333b89f | 2 | * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. |
c13d2ab4 RL |
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> | |
50cd4768 | 11 | #include <openssl/types.h> |
c13d2ab4 RL |
12 | #include <openssl/evp.h> |
13 | #include <openssl/core.h> | |
14 | #include "internal/cryptlib.h" | |
15 | #include "internal/thread_once.h" | |
c13d2ab4 RL |
16 | #include "internal/property.h" |
17 | #include "internal/core.h" | |
f7c16d48 | 18 | #include "internal/provider.h" |
baff732d | 19 | #include "internal/namemap.h" |
04cb5ec0 | 20 | #include "internal/property.h" |
706457b7 DMSP |
21 | #include "crypto/evp.h" /* evp_local.h needs it */ |
22 | #include "evp_local.h" | |
c13d2ab4 | 23 | |
695d195b RL |
24 | #define NAME_SEPARATOR ':' |
25 | ||
181ea366 | 26 | static void evp_method_store_free(void *vstore) |
c13d2ab4 RL |
27 | { |
28 | ossl_method_store_free(vstore); | |
29 | } | |
30 | ||
b4250010 | 31 | static void *evp_method_store_new(OSSL_LIB_CTX *ctx) |
c13d2ab4 | 32 | { |
1aedc35f | 33 | return ossl_method_store_new(ctx); |
c13d2ab4 RL |
34 | } |
35 | ||
36 | ||
b4250010 | 37 | static const OSSL_LIB_CTX_METHOD evp_method_store_method = { |
a16d2174 | 38 | /* We want evp_method_store to be cleaned up before the provider store */ |
8c627075 | 39 | OSSL_LIB_CTX_METHOD_PRIORITY_2, |
181ea366 RL |
40 | evp_method_store_new, |
41 | evp_method_store_free, | |
c13d2ab4 RL |
42 | }; |
43 | ||
c13d2ab4 | 44 | /* Data to be passed through ossl_method_construct() */ |
181ea366 | 45 | struct evp_method_data_st { |
b4250010 | 46 | OSSL_LIB_CTX *libctx; |
181ea366 RL |
47 | int operation_id; /* For get_evp_method_from_store() */ |
48 | int name_id; /* For get_evp_method_from_store() */ | |
49 | const char *names; /* For get_evp_method_from_store() */ | |
50 | const char *propquery; /* For get_evp_method_from_store() */ | |
ec0ce188 | 51 | |
9067cf6c RL |
52 | OSSL_METHOD_STORE *tmp_store; /* For get_tmp_evp_method_store() */ |
53 | ||
e3a2ba75 | 54 | unsigned int flag_construct_error_occurred : 1; |
ec0ce188 | 55 | |
309a78aa RL |
56 | void *(*method_from_algorithm)(int name_id, const OSSL_ALGORITHM *, |
57 | OSSL_PROVIDER *); | |
c13d2ab4 RL |
58 | int (*refcnt_up_method)(void *method); |
59 | void (*destruct_method)(void *method); | |
60 | }; | |
61 | ||
62 | /* | |
63 | * Generic routines to fetch / create EVP methods with ossl_method_construct() | |
64 | */ | |
9067cf6c | 65 | static void *get_tmp_evp_method_store(void *data) |
c13d2ab4 | 66 | { |
9067cf6c RL |
67 | struct evp_method_data_st *methdata = data; |
68 | ||
69 | if (methdata->tmp_store == NULL) | |
70 | methdata->tmp_store = ossl_method_store_new(methdata->libctx); | |
71 | return methdata->tmp_store; | |
c13d2ab4 RL |
72 | } |
73 | ||
181ea366 | 74 | static void dealloc_tmp_evp_method_store(void *store) |
c13d2ab4 RL |
75 | { |
76 | if (store != NULL) | |
77 | ossl_method_store_free(store); | |
78 | } | |
79 | ||
b4250010 | 80 | static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx) |
c13d2ab4 | 81 | { |
b4250010 DMSP |
82 | return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX, |
83 | &evp_method_store_method); | |
c13d2ab4 RL |
84 | } |
85 | ||
2ccb1b4e | 86 | /* |
64f849f4 DMSP |
87 | * To identify the method in the EVP method store, we mix the name identity |
88 | * with the operation identity, under the assumption that we don't have more | |
793b0586 | 89 | * than 2^23 names or more than 2^8 operation types. |
2ccb1b4e | 90 | * |
793b0586 | 91 | * The resulting identity is a 31-bit integer, composed like this: |
2ccb1b4e | 92 | * |
793b0586 | 93 | * +---------23 bits--------+-8 bits-+ |
2ccb1b4e RL |
94 | * | name identity | op id | |
95 | * +------------------------+--------+ | |
793b0586 RL |
96 | * |
97 | * We limit this composite number to 31 bits, thus leaving the top uint32_t | |
98 | * bit always zero, to avoid negative sign extension when downshifting after | |
99 | * this number happens to be passed to an int (which happens as soon as it's | |
100 | * passed to ossl_method_store_cache_set(), and it's in that form that it | |
101 | * gets passed along to filter_on_operation_id(), defined further down. | |
2ccb1b4e | 102 | */ |
793b0586 RL |
103 | #define METHOD_ID_OPERATION_MASK 0x000000FF |
104 | #define METHOD_ID_OPERATION_MAX ((1 << 8) - 1) | |
105 | #define METHOD_ID_NAME_MASK 0x7FFFFF00 | |
106 | #define METHOD_ID_NAME_OFFSET 8 | |
107 | #define METHOD_ID_NAME_MAX ((1 << 23) - 1) | |
b418980c | 108 | static uint32_t evp_method_id(int name_id, unsigned int operation_id) |
2ccb1b4e | 109 | { |
793b0586 RL |
110 | if (!ossl_assert(name_id > 0 && name_id <= METHOD_ID_NAME_MAX) |
111 | || !ossl_assert(operation_id > 0 | |
112 | && operation_id <= METHOD_ID_OPERATION_MAX)) | |
2ccb1b4e | 113 | return 0; |
793b0586 RL |
114 | return (((name_id << METHOD_ID_NAME_OFFSET) & METHOD_ID_NAME_MASK) |
115 | | (operation_id & METHOD_ID_OPERATION_MASK)); | |
2ccb1b4e RL |
116 | } |
117 | ||
6882652e | 118 | static void *get_evp_method_from_store(void *store, void *data) |
c13d2ab4 | 119 | { |
181ea366 | 120 | struct evp_method_data_st *methdata = data; |
c13d2ab4 | 121 | void *method = NULL; |
793b0586 | 122 | int name_id = 0; |
f7c16d48 | 123 | uint32_t meth_id; |
c13d2ab4 | 124 | |
f7c16d48 | 125 | /* |
181ea366 RL |
126 | * get_evp_method_from_store() is only called to try and get the method |
127 | * that evp_generic_fetch() is asking for, and the operation id as well | |
128 | * as the name or name id are passed via methdata. | |
f7c16d48 | 129 | */ |
793b0586 | 130 | if ((name_id = methdata->name_id) == 0 && methdata->names != NULL) { |
6882652e | 131 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); |
695d195b RL |
132 | const char *names = methdata->names; |
133 | const char *q = strchr(names, NAME_SEPARATOR); | |
134 | size_t l = (q == NULL ? strlen(names) : (size_t)(q - names)); | |
f7c16d48 RL |
135 | |
136 | if (namemap == 0) | |
137 | return NULL; | |
695d195b | 138 | name_id = ossl_namemap_name2num_n(namemap, names, l); |
f7c16d48 RL |
139 | } |
140 | ||
141 | if (name_id == 0 | |
b418980c | 142 | || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0) |
c13d2ab4 RL |
143 | return NULL; |
144 | ||
f7c16d48 | 145 | if (store == NULL |
6882652e | 146 | && (store = get_evp_method_store(methdata->libctx)) == NULL) |
2e49c054 RL |
147 | return NULL; |
148 | ||
bdbf2df2 P |
149 | if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, |
150 | &method)) | |
151 | return NULL; | |
c13d2ab4 RL |
152 | return method; |
153 | } | |
154 | ||
6882652e RL |
155 | static int put_evp_method_in_store(void *store, void *method, |
156 | const OSSL_PROVIDER *prov, | |
157 | const char *names, const char *propdef, | |
158 | void *data) | |
c13d2ab4 | 159 | { |
181ea366 | 160 | struct evp_method_data_st *methdata = data; |
2e49c054 | 161 | OSSL_NAMEMAP *namemap; |
f7c16d48 RL |
162 | int name_id; |
163 | uint32_t meth_id; | |
695d195b | 164 | size_t l = 0; |
dc46e3dd | 165 | |
f7c16d48 | 166 | /* |
181ea366 RL |
167 | * put_evp_method_in_store() is only called with an EVP method that was |
168 | * successfully created by construct_method() below, which means that | |
169 | * all the names should already be stored in the namemap with the same | |
170 | * numeric identity, so just use the first to get that identity. | |
f7c16d48 | 171 | */ |
695d195b RL |
172 | if (names != NULL) { |
173 | const char *q = strchr(names, NAME_SEPARATOR); | |
174 | ||
175 | l = (q == NULL ? strlen(names) : (size_t)(q - names)); | |
176 | } | |
177 | ||
6882652e | 178 | if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL |
695d195b | 179 | || (name_id = ossl_namemap_name2num_n(namemap, names, l)) == 0 |
6882652e | 180 | || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0) |
dc46e3dd | 181 | return 0; |
c13d2ab4 RL |
182 | |
183 | if (store == NULL | |
6882652e | 184 | && (store = get_evp_method_store(methdata->libctx)) == NULL) |
c13d2ab4 RL |
185 | return 0; |
186 | ||
f7c16d48 | 187 | return ossl_method_store_add(store, prov, meth_id, propdef, method, |
b1d40ddf RL |
188 | methdata->refcnt_up_method, |
189 | methdata->destruct_method); | |
c13d2ab4 RL |
190 | } |
191 | ||
f7c16d48 RL |
192 | /* |
193 | * The core fetching functionality passes the name of the implementation. | |
194 | * This function is responsible to getting an identity number for it. | |
195 | */ | |
36fa4d8a | 196 | static void *construct_evp_method(const OSSL_ALGORITHM *algodef, |
181ea366 | 197 | OSSL_PROVIDER *prov, void *data) |
c13d2ab4 | 198 | { |
f7c16d48 | 199 | /* |
181ea366 | 200 | * This function is only called if get_evp_method_from_store() returned |
f7c16d48 RL |
201 | * NULL, so it's safe to say that of all the spots to create a new |
202 | * namemap entry, this is it. Should the name already exist there, we | |
3d83c735 RL |
203 | * know that ossl_namemap_add_name() will return its corresponding |
204 | * number. | |
f7c16d48 | 205 | */ |
181ea366 | 206 | struct evp_method_data_st *methdata = data; |
a829b735 | 207 | OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); |
f7c16d48 | 208 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); |
36fa4d8a | 209 | const char *names = algodef->algorithm_names; |
3d83c735 | 210 | int name_id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR); |
ec0ce188 | 211 | void *method; |
c13d2ab4 | 212 | |
695d195b RL |
213 | if (name_id == 0) |
214 | return NULL; | |
ec0ce188 | 215 | |
309a78aa | 216 | method = methdata->method_from_algorithm(name_id, algodef, prov); |
ec0ce188 RL |
217 | |
218 | /* | |
219 | * Flag to indicate that there was actual construction errors. This | |
220 | * helps inner_evp_generic_fetch() determine what error it should | |
221 | * record on inaccessible algorithms. | |
222 | */ | |
223 | if (method == NULL) | |
e3a2ba75 | 224 | methdata->flag_construct_error_occurred = 1; |
ec0ce188 RL |
225 | |
226 | return method; | |
c13d2ab4 RL |
227 | } |
228 | ||
181ea366 | 229 | static void destruct_evp_method(void *method, void *data) |
c13d2ab4 | 230 | { |
181ea366 | 231 | struct evp_method_data_st *methdata = data; |
c13d2ab4 RL |
232 | |
233 | methdata->destruct_method(method); | |
234 | } | |
235 | ||
181ea366 | 236 | static void * |
9067cf6c | 237 | inner_evp_generic_fetch(struct evp_method_data_st *methdata, int operation_id, |
181ea366 RL |
238 | int name_id, const char *name, |
239 | const char *properties, | |
240 | void *(*new_method)(int name_id, | |
309a78aa | 241 | const OSSL_ALGORITHM *algodef, |
0ddf74bf | 242 | OSSL_PROVIDER *prov), |
181ea366 RL |
243 | int (*up_ref_method)(void *), |
244 | void (*free_method)(void *)) | |
c13d2ab4 | 245 | { |
9067cf6c RL |
246 | OSSL_METHOD_STORE *store = get_evp_method_store(methdata->libctx); |
247 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); | |
f7c16d48 | 248 | uint32_t meth_id = 0; |
c13d2ab4 | 249 | void *method = NULL; |
ec0ce188 | 250 | int unsupported = 0; |
c13d2ab4 | 251 | |
ec0ce188 | 252 | if (store == NULL || namemap == NULL) { |
d6d42cda | 253 | ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); |
e019da7b | 254 | return NULL; |
ec0ce188 | 255 | } |
e019da7b | 256 | |
2ccb1b4e RL |
257 | /* |
258 | * If there's ever an operation_id == 0 passed, we have an internal | |
259 | * programming error. | |
260 | */ | |
ec0ce188 | 261 | if (!ossl_assert(operation_id > 0)) { |
d6d42cda | 262 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); |
2ccb1b4e | 263 | return NULL; |
ec0ce188 | 264 | } |
2ccb1b4e RL |
265 | |
266 | /* | |
793b0586 | 267 | * If we have been passed both a name_id and a name, we have an |
f7c16d48 RL |
268 | * internal programming error. |
269 | */ | |
793b0586 | 270 | if (!ossl_assert(name_id == 0 || name == NULL)) { |
d6d42cda | 271 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); |
f7c16d48 | 272 | return NULL; |
ec0ce188 | 273 | } |
f7c16d48 RL |
274 | |
275 | /* If we haven't received a name id yet, try to get one for the name */ | |
793b0586 | 276 | if (name_id == 0 && name != NULL) |
f7c16d48 RL |
277 | name_id = ossl_namemap_name2num(namemap, name); |
278 | ||
279 | /* | |
181ea366 | 280 | * If we have a name id, calculate a method id with evp_method_id(). |
f7c16d48 | 281 | * |
181ea366 RL |
282 | * evp_method_id returns 0 if we have too many operations (more than |
283 | * about 2^8) or too many names (more than about 2^24). In that case, | |
284 | * we can't create any new method. | |
ec0ce188 | 285 | * For all intents and purposes, this is an internal error. |
2ccb1b4e | 286 | */ |
ec0ce188 | 287 | if (name_id != 0 && (meth_id = evp_method_id(name_id, operation_id)) == 0) { |
d6d42cda | 288 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); |
2ccb1b4e | 289 | return NULL; |
ec0ce188 RL |
290 | } |
291 | ||
292 | /* | |
293 | * If we haven't found the name yet, chances are that the algorithm to | |
294 | * be fetched is unsupported. | |
295 | */ | |
296 | if (name_id == 0) | |
297 | unsupported = 1; | |
2ccb1b4e | 298 | |
f7c16d48 RL |
299 | if (meth_id == 0 |
300 | || !ossl_method_store_cache_get(store, meth_id, properties, &method)) { | |
c13d2ab4 | 301 | OSSL_METHOD_CONSTRUCT_METHOD mcm = { |
9067cf6c | 302 | get_tmp_evp_method_store, |
181ea366 RL |
303 | get_evp_method_from_store, |
304 | put_evp_method_in_store, | |
305 | construct_evp_method, | |
306 | destruct_evp_method | |
c13d2ab4 | 307 | }; |
9067cf6c | 308 | |
9067cf6c RL |
309 | methdata->operation_id = operation_id; |
310 | methdata->name_id = name_id; | |
311 | methdata->names = name; | |
312 | methdata->propquery = properties; | |
313 | methdata->method_from_algorithm = new_method; | |
314 | methdata->refcnt_up_method = up_ref_method; | |
315 | methdata->destruct_method = free_method; | |
316 | methdata->flag_construct_error_occurred = 0; | |
317 | if ((method = ossl_method_construct(methdata->libctx, operation_id, | |
f7c16d48 | 318 | 0 /* !force_cache */, |
9067cf6c | 319 | &mcm, methdata)) != NULL) { |
2ccb1b4e RL |
320 | /* |
321 | * If construction did create a method for us, we know that | |
181ea366 RL |
322 | * there is a correct name_id and meth_id, since those have |
323 | * already been calculated in get_evp_method_from_store() and | |
324 | * put_evp_method_in_store() above. | |
2ccb1b4e | 325 | */ |
f7c16d48 RL |
326 | if (name_id == 0) |
327 | name_id = ossl_namemap_name2num(namemap, name); | |
b418980c | 328 | meth_id = evp_method_id(name_id, operation_id); |
793b0586 RL |
329 | if (name_id != 0) |
330 | ossl_method_store_cache_set(store, meth_id, properties, method, | |
331 | up_ref_method, free_method); | |
2ccb1b4e | 332 | } |
ec0ce188 RL |
333 | |
334 | /* | |
335 | * If we never were in the constructor, the algorithm to be fetched | |
336 | * is unsupported. | |
337 | */ | |
9067cf6c | 338 | unsupported = !methdata->flag_construct_error_occurred; |
c13d2ab4 RL |
339 | } |
340 | ||
793b0586 | 341 | if ((name_id != 0 || name != NULL) && method == NULL) { |
d6d42cda | 342 | int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED; |
cb929645 | 343 | |
ec0ce188 RL |
344 | if (name == NULL) |
345 | name = ossl_namemap_num2name(namemap, name_id, 0); | |
346 | ERR_raise_data(ERR_LIB_EVP, code, | |
347 | "%s, Algorithm (%s : %d), Properties (%s)", | |
9067cf6c | 348 | ossl_lib_ctx_get_descriptor(methdata->libctx), |
ec0ce188 RL |
349 | name = NULL ? "<null>" : name, name_id, |
350 | properties == NULL ? "<null>" : properties); | |
351 | } | |
352 | ||
353 | return method; | |
cfbd76c1 | 354 | } |
cfbd76c1 | 355 | |
b4250010 | 356 | void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id, |
f7c16d48 RL |
357 | const char *name, const char *properties, |
358 | void *(*new_method)(int name_id, | |
309a78aa | 359 | const OSSL_ALGORITHM *algodef, |
0ddf74bf | 360 | OSSL_PROVIDER *prov), |
f7c16d48 RL |
361 | int (*up_ref_method)(void *), |
362 | void (*free_method)(void *)) | |
363 | { | |
9067cf6c RL |
364 | struct evp_method_data_st methdata; |
365 | void *method; | |
366 | ||
367 | methdata.libctx = libctx; | |
368 | methdata.tmp_store = NULL; | |
369 | method = inner_evp_generic_fetch(&methdata, | |
370 | operation_id, 0, name, properties, | |
371 | new_method, up_ref_method, free_method); | |
372 | dealloc_tmp_evp_method_store(methdata.tmp_store); | |
373 | return method; | |
f7c16d48 RL |
374 | } |
375 | ||
376 | /* | |
377 | * evp_generic_fetch_by_number() is special, and only returns methods for | |
378 | * already known names, i.e. it refuses to work if no name_id can be found | |
379 | * (it's considered an internal programming error). | |
380 | * This is meant to be used when one method needs to fetch an associated | |
381 | * other method. | |
382 | */ | |
b4250010 | 383 | void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id, |
f7c16d48 RL |
384 | int name_id, const char *properties, |
385 | void *(*new_method)(int name_id, | |
309a78aa | 386 | const OSSL_ALGORITHM *algodef, |
0ddf74bf | 387 | OSSL_PROVIDER *prov), |
f7c16d48 RL |
388 | int (*up_ref_method)(void *), |
389 | void (*free_method)(void *)) | |
390 | { | |
9067cf6c RL |
391 | struct evp_method_data_st methdata; |
392 | void *method; | |
393 | ||
394 | methdata.libctx = libctx; | |
395 | methdata.tmp_store = NULL; | |
396 | method = inner_evp_generic_fetch(&methdata, | |
397 | operation_id, name_id, NULL, properties, | |
398 | new_method, up_ref_method, free_method); | |
399 | dealloc_tmp_evp_method_store(methdata.tmp_store); | |
400 | return method; | |
f7c16d48 RL |
401 | } |
402 | ||
860ecfd7 | 403 | int evp_method_store_flush(OSSL_LIB_CTX *libctx) |
04cb5ec0 SL |
404 | { |
405 | OSSL_METHOD_STORE *store = get_evp_method_store(libctx); | |
406 | ||
407 | if (store != NULL) | |
860ecfd7 P |
408 | return ossl_method_store_flush_cache(store, 1); |
409 | return 1; | |
04cb5ec0 SL |
410 | } |
411 | ||
b4250010 | 412 | static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx, |
e6c54619 | 413 | OSSL_PROPERTY_LIST *def_prop, |
b1c053ac MC |
414 | int loadconfig, |
415 | int mirrored) | |
cb929645 | 416 | { |
181ea366 | 417 | OSSL_METHOD_STORE *store = get_evp_method_store(libctx); |
e6c54619 | 418 | OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig); |
f9e504e8 | 419 | |
447588b6 | 420 | if (plp != NULL && store != NULL) { |
b1c053ac | 421 | #ifndef FIPS_MODULE |
447588b6 MC |
422 | char *propstr = NULL; |
423 | size_t strsz; | |
424 | ||
b1c053ac MC |
425 | if (mirrored) { |
426 | if (ossl_global_properties_no_mirrored(libctx)) | |
427 | return 0; | |
428 | } else { | |
429 | /* | |
430 | * These properties have been explicitly set on this libctx, so | |
431 | * don't allow any mirroring from a parent libctx. | |
432 | */ | |
433 | ossl_global_properties_stop_mirroring(libctx); | |
434 | } | |
435 | ||
447588b6 MC |
436 | strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0); |
437 | if (strsz > 0) | |
438 | propstr = OPENSSL_malloc(strsz); | |
439 | if (propstr == NULL) { | |
440 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); | |
441 | return 0; | |
442 | } | |
443 | if (ossl_property_list_to_string(libctx, def_prop, propstr, | |
444 | strsz) == 0) { | |
445 | OPENSSL_free(propstr); | |
446 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); | |
447 | return 0; | |
448 | } | |
447588b6 MC |
449 | ossl_provider_default_props_update(libctx, propstr); |
450 | OPENSSL_free(propstr); | |
b1c053ac MC |
451 | #endif |
452 | ossl_property_free(*plp); | |
453 | *plp = def_prop; | |
f9e504e8 | 454 | if (store != NULL) |
860ecfd7 | 455 | return ossl_method_store_flush_cache(store, 0); |
f9e504e8 | 456 | } |
9311d0c4 | 457 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); |
cb929645 RL |
458 | return 0; |
459 | } | |
3d96a51c | 460 | |
b4250010 | 461 | int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq, |
b1c053ac | 462 | int loadconfig, int mirrored) |
f9e504e8 P |
463 | { |
464 | OSSL_PROPERTY_LIST *pl = NULL; | |
465 | ||
1e08f3ba | 466 | if (propq != NULL && (pl = ossl_parse_query(libctx, propq, 1)) == NULL) { |
9311d0c4 | 467 | ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR); |
f9e504e8 P |
468 | return 0; |
469 | } | |
b1c053ac | 470 | if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) { |
e2ed740e MC |
471 | ossl_property_free(pl); |
472 | return 0; | |
473 | } | |
474 | return 1; | |
f9e504e8 P |
475 | } |
476 | ||
b4250010 | 477 | int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq) |
e6c54619 | 478 | { |
b1c053ac | 479 | return evp_set_default_properties_int(libctx, propq, 1, 0); |
e6c54619 | 480 | } |
e0624f0d | 481 | |
b4250010 | 482 | static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq) |
e0624f0d | 483 | { |
e6c54619 | 484 | OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1); |
f9e504e8 P |
485 | OSSL_PROPERTY_LIST *pl1, *pl2; |
486 | ||
487 | if (propq == NULL) | |
488 | return 1; | |
489 | if (plp == NULL || *plp == NULL) | |
490 | return EVP_set_default_properties(libctx, propq); | |
1e08f3ba | 491 | if ((pl1 = ossl_parse_query(libctx, propq, 1)) == NULL) { |
9311d0c4 | 492 | ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR); |
f9e504e8 P |
493 | return 0; |
494 | } | |
495 | pl2 = ossl_property_merge(pl1, *plp); | |
496 | ossl_property_free(pl1); | |
497 | if (pl2 == NULL) { | |
9311d0c4 | 498 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
f9e504e8 P |
499 | return 0; |
500 | } | |
b1c053ac | 501 | if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) { |
e2ed740e MC |
502 | ossl_property_free(pl2); |
503 | return 0; | |
504 | } | |
505 | return 1; | |
e0624f0d SL |
506 | } |
507 | ||
b4250010 | 508 | static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx, |
e0624f0d SL |
509 | const char *prop_name) |
510 | { | |
e6c54619 | 511 | OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1); |
e0624f0d | 512 | |
f9e504e8 | 513 | return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp); |
e0624f0d SL |
514 | } |
515 | ||
b4250010 | 516 | int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx) |
e0624f0d SL |
517 | { |
518 | return evp_default_property_is_enabled(libctx, "fips"); | |
519 | } | |
520 | ||
b4250010 | 521 | int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable) |
e0624f0d SL |
522 | { |
523 | const char *query = (enable != 0) ? "fips=yes" : "-fips"; | |
524 | ||
525 | return evp_default_properties_merge(libctx, query); | |
526 | } | |
527 | ||
447588b6 MC |
528 | char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig) |
529 | { | |
530 | OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig); | |
531 | char *propstr = NULL; | |
532 | size_t sz; | |
533 | ||
72f62f44 P |
534 | if (plp == NULL) |
535 | return OPENSSL_strdup(""); | |
536 | ||
447588b6 MC |
537 | sz = ossl_property_list_to_string(libctx, *plp, NULL, 0); |
538 | if (sz == 0) { | |
539 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); | |
540 | return NULL; | |
541 | } | |
542 | ||
543 | propstr = OPENSSL_malloc(sz); | |
544 | if (propstr == NULL) { | |
545 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); | |
546 | return NULL; | |
547 | } | |
548 | if (ossl_property_list_to_string(libctx, *plp, propstr, sz) == 0) { | |
549 | ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); | |
550 | OPENSSL_free(propstr); | |
551 | return NULL; | |
552 | } | |
553 | return propstr; | |
554 | } | |
e0624f0d | 555 | |
793b0586 RL |
556 | struct filter_data_st { |
557 | int operation_id; | |
3d96a51c RL |
558 | void (*user_fn)(void *method, void *arg); |
559 | void *user_arg; | |
3d96a51c RL |
560 | }; |
561 | ||
793b0586 | 562 | static void filter_on_operation_id(int id, void *method, void *arg) |
3d96a51c | 563 | { |
793b0586 | 564 | struct filter_data_st *data = arg; |
3d96a51c | 565 | |
793b0586 | 566 | if ((id & METHOD_ID_OPERATION_MASK) == data->operation_id) |
3d96a51c | 567 | data->user_fn(method, data->user_arg); |
3d96a51c RL |
568 | } |
569 | ||
b4250010 | 570 | void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id, |
3d96a51c RL |
571 | void (*user_fn)(void *method, void *arg), |
572 | void *user_arg, | |
f7c16d48 | 573 | void *(*new_method)(int name_id, |
309a78aa | 574 | const OSSL_ALGORITHM *algodef, |
0ddf74bf | 575 | OSSL_PROVIDER *prov), |
793b0586 | 576 | int (*up_ref_method)(void *), |
3d96a51c RL |
577 | void (*free_method)(void *)) |
578 | { | |
793b0586 RL |
579 | struct evp_method_data_st methdata; |
580 | struct filter_data_st data; | |
581 | ||
582 | methdata.libctx = libctx; | |
583 | methdata.tmp_store = NULL; | |
584 | (void)inner_evp_generic_fetch(&methdata, operation_id, 0, NULL, NULL, | |
585 | new_method, up_ref_method, free_method); | |
3d96a51c | 586 | |
793b0586 | 587 | data.operation_id = operation_id; |
3d96a51c RL |
588 | data.user_fn = user_fn; |
589 | data.user_arg = user_arg; | |
793b0586 RL |
590 | if (methdata.tmp_store != NULL) |
591 | ossl_method_store_do_all(methdata.tmp_store, &filter_on_operation_id, | |
592 | &data); | |
593 | ossl_method_store_do_all(get_evp_method_store(libctx), | |
594 | &filter_on_operation_id, &data); | |
595 | dealloc_tmp_evp_method_store(methdata.tmp_store); | |
3d96a51c | 596 | } |
f7c16d48 | 597 | |
e4a1d023 RL |
598 | int evp_is_a(OSSL_PROVIDER *prov, int number, |
599 | const char *legacy_name, const char *name) | |
7cfa1717 | 600 | { |
e4a1d023 RL |
601 | /* |
602 | * For a |prov| that is NULL, the library context will be NULL | |
603 | */ | |
a829b735 | 604 | OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); |
7cfa1717 RL |
605 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); |
606 | ||
e4a1d023 RL |
607 | if (prov == NULL) |
608 | number = ossl_namemap_name2num(namemap, legacy_name); | |
7cfa1717 RL |
609 | return ossl_namemap_name2num(namemap, name) == number; |
610 | } | |
32040838 | 611 | |
d84f5515 MC |
612 | int evp_names_do_all(OSSL_PROVIDER *prov, int number, |
613 | void (*fn)(const char *name, void *data), | |
614 | void *data) | |
32040838 | 615 | { |
a829b735 | 616 | OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov); |
32040838 RL |
617 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); |
618 | ||
d84f5515 | 619 | return ossl_namemap_doall_names(namemap, number, fn, data); |
32040838 | 620 | } |