/src/openssl/crypto/evp/skeymgmt_meth.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 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/crypto.h> |
11 | | #include <openssl/core_dispatch.h> |
12 | | #include <openssl/evp.h> |
13 | | #include <openssl/err.h> |
14 | | #include "internal/core.h" |
15 | | #include "internal/provider.h" |
16 | | #include "internal/refcount.h" |
17 | | #include "crypto/evp.h" |
18 | | #include "evp_local.h" |
19 | | |
20 | | static void evp_skeymgmt_free(void *s); |
21 | | |
22 | | void *evp_skeymgmt_generate(const EVP_SKEYMGMT *skeymgmt, const OSSL_PARAM params[]) |
23 | 0 | { |
24 | 0 | void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); |
25 | |
|
26 | 0 | return (skeymgmt->generate != NULL) ? skeymgmt->generate(provctx, params) : NULL; |
27 | 0 | } |
28 | | |
29 | | void *evp_skeymgmt_import(const EVP_SKEYMGMT *skeymgmt, int selection, const OSSL_PARAM params[]) |
30 | 0 | { |
31 | 0 | void *provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); |
32 | | |
33 | | /* This is mandatory, no need to check for its presence */ |
34 | 0 | return skeymgmt->import(provctx, selection, params); |
35 | 0 | } |
36 | | |
37 | | int evp_skeymgmt_export(const EVP_SKEYMGMT *skeymgmt, void *keydata, |
38 | | int selection, OSSL_CALLBACK *param_cb, void *cbarg) |
39 | 0 | { |
40 | | /* This is mandatory, no need to check for its presence */ |
41 | 0 | return skeymgmt->export(keydata, selection, param_cb, cbarg); |
42 | 0 | } |
43 | | |
44 | | void evp_skeymgmt_freedata(const EVP_SKEYMGMT *skeymgmt, void *keydata) |
45 | 0 | { |
46 | | /* This is mandatory, no need to check for its presence */ |
47 | 0 | skeymgmt->free(keydata); |
48 | 0 | } |
49 | | |
50 | | static void *skeymgmt_new(void) |
51 | 0 | { |
52 | 0 | EVP_SKEYMGMT *skeymgmt = NULL; |
53 | |
|
54 | 0 | if ((skeymgmt = OPENSSL_zalloc(sizeof(*skeymgmt))) == NULL) |
55 | 0 | return NULL; |
56 | 0 | if (!CRYPTO_NEW_REF(&skeymgmt->refcnt, 1)) { |
57 | 0 | evp_skeymgmt_free(skeymgmt); |
58 | 0 | return NULL; |
59 | 0 | } |
60 | 0 | return skeymgmt; |
61 | 0 | } |
62 | | |
63 | | static void *skeymgmt_from_algorithm(int name_id, |
64 | | const OSSL_ALGORITHM *algodef, |
65 | | OSSL_PROVIDER *prov, int no_store) |
66 | 0 | { |
67 | 0 | const OSSL_DISPATCH *fns = algodef->implementation; |
68 | 0 | EVP_SKEYMGMT *skeymgmt = NULL; |
69 | |
|
70 | 0 | if ((skeymgmt = skeymgmt_new()) == NULL) |
71 | 0 | return NULL; |
72 | | |
73 | 0 | skeymgmt->name_id = name_id; |
74 | 0 | skeymgmt->no_store = no_store; |
75 | 0 | if ((skeymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { |
76 | 0 | evp_skeymgmt_free(skeymgmt); |
77 | 0 | return NULL; |
78 | 0 | } |
79 | 0 | skeymgmt->description = algodef->algorithm_description; |
80 | |
|
81 | 0 | for (; fns->function_id != 0; fns++) { |
82 | 0 | switch (fns->function_id) { |
83 | 0 | case OSSL_FUNC_SKEYMGMT_FREE: |
84 | 0 | if (skeymgmt->free == NULL) |
85 | 0 | skeymgmt->free = OSSL_FUNC_skeymgmt_free(fns); |
86 | 0 | break; |
87 | 0 | case OSSL_FUNC_SKEYMGMT_IMPORT: |
88 | 0 | if (skeymgmt->import == NULL) |
89 | 0 | skeymgmt->import = OSSL_FUNC_skeymgmt_import(fns); |
90 | 0 | break; |
91 | 0 | case OSSL_FUNC_SKEYMGMT_EXPORT: |
92 | 0 | if (skeymgmt->export == NULL) |
93 | 0 | skeymgmt->export = OSSL_FUNC_skeymgmt_export(fns); |
94 | 0 | break; |
95 | 0 | case OSSL_FUNC_SKEYMGMT_GENERATE: |
96 | 0 | if (skeymgmt->generate == NULL) |
97 | 0 | skeymgmt->generate = OSSL_FUNC_skeymgmt_generate(fns); |
98 | 0 | break; |
99 | 0 | case OSSL_FUNC_SKEYMGMT_GET_KEY_ID: |
100 | 0 | if (skeymgmt->get_key_id == NULL) |
101 | 0 | skeymgmt->get_key_id = OSSL_FUNC_skeymgmt_get_key_id(fns); |
102 | 0 | break; |
103 | 0 | case OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS: |
104 | 0 | if (skeymgmt->imp_params == NULL) |
105 | 0 | skeymgmt->imp_params = OSSL_FUNC_skeymgmt_imp_settable_params(fns); |
106 | 0 | break; |
107 | 0 | case OSSL_FUNC_SKEYMGMT_GEN_SETTABLE_PARAMS: |
108 | 0 | if (skeymgmt->gen_params == NULL) |
109 | 0 | skeymgmt->gen_params = OSSL_FUNC_skeymgmt_gen_settable_params(fns); |
110 | 0 | break; |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | /* Check that the provider is sensible */ |
115 | 0 | if (skeymgmt->free == NULL |
116 | 0 | || skeymgmt->import == NULL |
117 | 0 | || skeymgmt->export == NULL) { |
118 | 0 | evp_skeymgmt_free(skeymgmt); |
119 | 0 | ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); |
120 | 0 | return NULL; |
121 | 0 | } |
122 | | |
123 | 0 | if (!ossl_provider_up_ref(prov)) { |
124 | 0 | evp_skeymgmt_free(skeymgmt); |
125 | 0 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); |
126 | 0 | return NULL; |
127 | 0 | } |
128 | 0 | skeymgmt->prov = prov; |
129 | |
|
130 | 0 | return skeymgmt; |
131 | 0 | } |
132 | | |
133 | | static int evp_skeymgmt_up_ref(void *s) |
134 | 0 | { |
135 | 0 | EVP_SKEYMGMT *skeymgmt = (EVP_SKEYMGMT *)s; |
136 | 0 | int ref = 0; |
137 | |
|
138 | 0 | CRYPTO_UP_REF(&skeymgmt->refcnt, &ref); |
139 | 0 | return 1; |
140 | 0 | } |
141 | | |
142 | | static void evp_skeymgmt_free(void *s) |
143 | 0 | { |
144 | 0 | EVP_SKEYMGMT *skeymgmt = (EVP_SKEYMGMT *)s; |
145 | 0 | int ref = 0; |
146 | |
|
147 | 0 | if (skeymgmt == NULL) |
148 | 0 | return; |
149 | | |
150 | 0 | CRYPTO_DOWN_REF(&skeymgmt->refcnt, &ref); |
151 | 0 | if (ref > 0) |
152 | 0 | return; |
153 | 0 | OPENSSL_free(skeymgmt->type_name); |
154 | 0 | ossl_provider_free(skeymgmt->prov); |
155 | 0 | CRYPTO_FREE_REF(&skeymgmt->refcnt); |
156 | 0 | OPENSSL_free(skeymgmt); |
157 | 0 | } |
158 | | |
159 | | EVP_SKEYMGMT *evp_skeymgmt_fetch_from_prov(OSSL_PROVIDER *prov, |
160 | | const char *name, |
161 | | const char *properties) |
162 | 0 | { |
163 | 0 | return evp_generic_fetch_from_prov(prov, |
164 | 0 | OSSL_OP_SKEYMGMT, |
165 | 0 | name, properties, |
166 | 0 | skeymgmt_from_algorithm, |
167 | 0 | evp_skeymgmt_up_ref, |
168 | 0 | evp_skeymgmt_free); |
169 | 0 | } |
170 | | |
171 | | EVP_SKEYMGMT *EVP_SKEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, |
172 | | const char *properties) |
173 | 0 | { |
174 | 0 | return evp_generic_fetch(ctx, OSSL_OP_SKEYMGMT, algorithm, properties, |
175 | 0 | skeymgmt_from_algorithm, |
176 | 0 | evp_skeymgmt_up_ref, |
177 | 0 | evp_skeymgmt_free); |
178 | 0 | } |
179 | | |
180 | | int EVP_SKEYMGMT_up_ref(EVP_SKEYMGMT *skeymgmt) |
181 | 0 | { |
182 | | #ifdef OPENSSL_NO_CACHED_FETCH |
183 | | return evp_skeymgmt_up_ref(skeymgmt); |
184 | | #else |
185 | 0 | if (skeymgmt->no_store != 0) |
186 | 0 | return evp_skeymgmt_up_ref(skeymgmt); |
187 | 0 | return 1; |
188 | 0 | #endif |
189 | 0 | } |
190 | | |
191 | | void EVP_SKEYMGMT_free(EVP_SKEYMGMT *skeymgmt) |
192 | 0 | { |
193 | | #ifdef OPENSSL_NO_CACHED_FETCH |
194 | | evp_skeymgmt_free(skeymgmt); |
195 | | #else |
196 | 0 | if (skeymgmt != NULL && (skeymgmt->no_store != 0)) |
197 | 0 | evp_skeymgmt_free(skeymgmt); |
198 | 0 | #endif |
199 | 0 | } |
200 | | |
201 | | const OSSL_PROVIDER *EVP_SKEYMGMT_get0_provider(const EVP_SKEYMGMT *skeymgmt) |
202 | 0 | { |
203 | 0 | return (skeymgmt != NULL) ? skeymgmt->prov : NULL; |
204 | 0 | } |
205 | | |
206 | | const char *EVP_SKEYMGMT_get0_description(const EVP_SKEYMGMT *skeymgmt) |
207 | 0 | { |
208 | 0 | return (skeymgmt != NULL) ? skeymgmt->description : NULL; |
209 | 0 | } |
210 | | |
211 | | const char *EVP_SKEYMGMT_get0_name(const EVP_SKEYMGMT *skeymgmt) |
212 | 0 | { |
213 | 0 | return (skeymgmt != NULL) ? skeymgmt->type_name : NULL; |
214 | 0 | } |
215 | | |
216 | | int EVP_SKEYMGMT_is_a(const EVP_SKEYMGMT *skeymgmt, const char *name) |
217 | 0 | { |
218 | 0 | return skeymgmt != NULL |
219 | 0 | && evp_is_a(skeymgmt->prov, skeymgmt->name_id, NULL, name); |
220 | 0 | } |
221 | | |
222 | | void EVP_SKEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx, |
223 | | void (*fn)(EVP_SKEYMGMT *skeymgmt, void *arg), |
224 | | void *arg) |
225 | 0 | { |
226 | 0 | struct EVP_SKEYMGMT_do_all_provided_thunk t; |
227 | |
|
228 | 0 | t.fn = fn; |
229 | 0 | t.arg = arg; |
230 | 0 | evp_generic_do_all(libctx, OSSL_OP_SKEYMGMT, |
231 | 0 | EVP_SKEYMGMT_do_all_provided_thunk, &t, |
232 | 0 | skeymgmt_from_algorithm, |
233 | 0 | evp_skeymgmt_up_ref, |
234 | 0 | evp_skeymgmt_free); |
235 | 0 | } |
236 | | |
237 | | int EVP_SKEYMGMT_names_do_all(const EVP_SKEYMGMT *skeymgmt, |
238 | | void (*fn)(const char *name, void *data), |
239 | | void *data) |
240 | 0 | { |
241 | 0 | if (skeymgmt == NULL) |
242 | 0 | return 0; |
243 | | |
244 | 0 | if (skeymgmt->prov != NULL) |
245 | 0 | return evp_names_do_all(skeymgmt->prov, skeymgmt->name_id, fn, data); |
246 | | |
247 | 0 | return 1; |
248 | 0 | } |
249 | | |
250 | | const OSSL_PARAM *EVP_SKEYMGMT_get0_gen_settable_params(const EVP_SKEYMGMT *skeymgmt) |
251 | 0 | { |
252 | 0 | void *provctx = NULL; |
253 | |
|
254 | 0 | if (skeymgmt == NULL) |
255 | 0 | return 0; |
256 | | |
257 | 0 | provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); |
258 | |
|
259 | 0 | return (skeymgmt->gen_params != NULL) ? skeymgmt->gen_params(provctx) : NULL; |
260 | 0 | } |
261 | | |
262 | | const OSSL_PARAM *EVP_SKEYMGMT_get0_imp_settable_params(const EVP_SKEYMGMT *skeymgmt) |
263 | 0 | { |
264 | 0 | void *provctx = NULL; |
265 | |
|
266 | 0 | if (skeymgmt == NULL) |
267 | 0 | return 0; |
268 | | |
269 | 0 | provctx = ossl_provider_ctx(EVP_SKEYMGMT_get0_provider(skeymgmt)); |
270 | |
|
271 | 0 | return (skeymgmt->imp_params != NULL) ? skeymgmt->imp_params(provctx) : NULL; |
272 | 0 | } |