]>
Commit | Line | Data |
---|---|---|
c13d2ab4 RL |
1 | /* |
2 | * Copyright 2019 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/ossl_typ.h> | |
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" | |
baff732d | 18 | #include "internal/namemap.h" |
c13d2ab4 RL |
19 | #include "internal/evp_int.h" /* evp_locl.h needs it */ |
20 | #include "evp_locl.h" | |
21 | ||
c13d2ab4 RL |
22 | static void default_method_store_free(void *vstore) |
23 | { | |
24 | ossl_method_store_free(vstore); | |
25 | } | |
26 | ||
1aedc35f | 27 | static void *default_method_store_new(OPENSSL_CTX *ctx) |
c13d2ab4 | 28 | { |
1aedc35f | 29 | return ossl_method_store_new(ctx); |
c13d2ab4 RL |
30 | } |
31 | ||
32 | ||
33 | static const OPENSSL_CTX_METHOD default_method_store_method = { | |
34 | default_method_store_new, | |
35 | default_method_store_free, | |
36 | }; | |
37 | ||
c13d2ab4 RL |
38 | /* Data to be passed through ossl_method_construct() */ |
39 | struct method_data_st { | |
baff732d | 40 | OPENSSL_CTX *libctx; |
c13d2ab4 RL |
41 | const char *name; |
42 | int nid; | |
43 | OSSL_METHOD_CONSTRUCT_METHOD *mcm; | |
44 | void *(*method_from_dispatch)(int nid, const OSSL_DISPATCH *, | |
45 | OSSL_PROVIDER *); | |
46 | int (*refcnt_up_method)(void *method); | |
47 | void (*destruct_method)(void *method); | |
dc46e3dd | 48 | int (*nid_method)(void *method); |
c13d2ab4 RL |
49 | }; |
50 | ||
51 | /* | |
52 | * Generic routines to fetch / create EVP methods with ossl_method_construct() | |
53 | */ | |
1aedc35f | 54 | static void *alloc_tmp_method_store(OPENSSL_CTX *ctx) |
c13d2ab4 | 55 | { |
1aedc35f | 56 | return ossl_method_store_new(ctx); |
c13d2ab4 RL |
57 | } |
58 | ||
59 | static void dealloc_tmp_method_store(void *store) | |
60 | { | |
61 | if (store != NULL) | |
62 | ossl_method_store_free(store); | |
63 | } | |
64 | ||
cb929645 | 65 | static OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx) |
c13d2ab4 | 66 | { |
1aedc35f MC |
67 | return openssl_ctx_get_data(libctx, OPENSSL_CTX_DEFAULT_METHOD_STORE_INDEX, |
68 | &default_method_store_method); | |
c13d2ab4 RL |
69 | } |
70 | ||
71 | static void *get_method_from_store(OPENSSL_CTX *libctx, void *store, | |
72 | const char *propquery, void *data) | |
73 | { | |
74 | struct method_data_st *methdata = data; | |
75 | void *method = NULL; | |
76 | ||
77 | if (store == NULL | |
78 | && (store = get_default_method_store(libctx)) == NULL) | |
79 | return NULL; | |
80 | ||
81 | (void)ossl_method_store_fetch(store, methdata->nid, propquery, &method); | |
82 | ||
83 | if (method != NULL | |
84 | && !methdata->refcnt_up_method(method)) { | |
85 | method = NULL; | |
86 | } | |
87 | return method; | |
88 | } | |
89 | ||
90 | static int put_method_in_store(OPENSSL_CTX *libctx, void *store, | |
dc46e3dd MC |
91 | const char *propdef, |
92 | void *method, void *data) | |
c13d2ab4 RL |
93 | { |
94 | struct method_data_st *methdata = data; | |
dc46e3dd MC |
95 | int nid = methdata->nid_method(method); |
96 | ||
baff732d | 97 | if (nid == 0) |
dc46e3dd | 98 | return 0; |
c13d2ab4 RL |
99 | |
100 | if (store == NULL | |
101 | && (store = get_default_method_store(libctx)) == NULL) | |
102 | return 0; | |
103 | ||
104 | if (methdata->refcnt_up_method(method) | |
dc46e3dd | 105 | && ossl_method_store_add(store, nid, propdef, method, |
c13d2ab4 RL |
106 | methdata->destruct_method)) |
107 | return 1; | |
108 | return 0; | |
109 | } | |
110 | ||
dc46e3dd MC |
111 | static void *construct_method(const char *algorithm_name, |
112 | const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov, | |
c13d2ab4 RL |
113 | void *data) |
114 | { | |
115 | struct method_data_st *methdata = data; | |
baff732d RL |
116 | OSSL_NAMEMAP *namemap; |
117 | int nid; | |
c13d2ab4 | 118 | |
baff732d RL |
119 | if ((namemap = ossl_namemap_stored(methdata->libctx)) == NULL |
120 | || (nid = ossl_namemap_add(namemap, algorithm_name)) == 0) | |
c13d2ab4 RL |
121 | return NULL; |
122 | ||
baff732d | 123 | return methdata->method_from_dispatch(nid, fns, prov); |
c13d2ab4 RL |
124 | } |
125 | ||
126 | static void destruct_method(void *method, void *data) | |
127 | { | |
128 | struct method_data_st *methdata = data; | |
129 | ||
130 | methdata->destruct_method(method); | |
131 | } | |
132 | ||
133 | void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id, | |
134 | const char *algorithm, const char *properties, | |
135 | void *(*new_method)(int nid, const OSSL_DISPATCH *fns, | |
136 | OSSL_PROVIDER *prov), | |
137 | int (*upref_method)(void *), | |
dc46e3dd MC |
138 | void (*free_method)(void *), |
139 | int (*nid_method)(void *)) | |
c13d2ab4 | 140 | { |
e019da7b | 141 | OSSL_METHOD_STORE *store = get_default_method_store(libctx); |
baff732d RL |
142 | OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); |
143 | int nid; | |
c13d2ab4 RL |
144 | void *method = NULL; |
145 | ||
baff732d | 146 | if (store == NULL || namemap == NULL) |
e019da7b RL |
147 | return NULL; |
148 | ||
baff732d | 149 | if ((nid = ossl_namemap_number(namemap, algorithm)) == 0 |
e019da7b | 150 | || !ossl_method_store_cache_get(store, nid, properties, &method)) { |
c13d2ab4 RL |
151 | OSSL_METHOD_CONSTRUCT_METHOD mcm = { |
152 | alloc_tmp_method_store, | |
153 | dealloc_tmp_method_store, | |
154 | get_method_from_store, | |
155 | put_method_in_store, | |
156 | construct_method, | |
157 | destruct_method | |
158 | }; | |
159 | struct method_data_st mcmdata; | |
160 | ||
161 | mcmdata.nid = nid; | |
162 | mcmdata.mcm = &mcm; | |
baff732d | 163 | mcmdata.libctx = libctx; |
c13d2ab4 RL |
164 | mcmdata.method_from_dispatch = new_method; |
165 | mcmdata.destruct_method = free_method; | |
166 | mcmdata.refcnt_up_method = upref_method; | |
167 | mcmdata.destruct_method = free_method; | |
dc46e3dd | 168 | mcmdata.nid_method = nid_method; |
c13d2ab4 RL |
169 | method = ossl_method_construct(libctx, operation_id, algorithm, |
170 | properties, 0 /* !force_cache */, | |
171 | &mcm, &mcmdata); | |
e019da7b RL |
172 | ossl_method_store_cache_set(store, nid, properties, method); |
173 | } else { | |
174 | upref_method(method); | |
c13d2ab4 RL |
175 | } |
176 | ||
177 | return method; | |
178 | } | |
cb929645 RL |
179 | |
180 | int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq) | |
181 | { | |
182 | OSSL_METHOD_STORE *store = get_default_method_store(libctx); | |
183 | ||
184 | if (store != NULL) | |
185 | return ossl_method_store_set_global_properties(store, propq); | |
186 | EVPerr(EVP_F_EVP_SET_DEFAULT_PROPERTIES, ERR_R_INTERNAL_ERROR); | |
187 | return 0; | |
188 | } |