]>
Commit | Line | Data |
---|---|---|
c13d2ab4 RL |
1 | =pod |
2 | ||
3 | =head1 NAME | |
4 | ||
16ff70a5 | 5 | evp_generic_fetch, evp_generic_fetch_from_prov |
f7c16d48 | 6 | - generic algorithm fetchers and method creators for EVP |
c13d2ab4 RL |
7 | |
8 | =head1 SYNOPSIS | |
9 | ||
10 | /* Only for EVP source */ | |
706457b7 | 11 | #include "evp_local.h" |
c13d2ab4 | 12 | |
b4250010 | 13 | void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id, |
2e49c054 | 14 | const char *name, const char *properties, |
f7c16d48 | 15 | void *(*new_method)(int name_id, |
3ca9d210 RL |
16 | const OSSL_DISPATCH *fns, |
17 | OSSL_PROVIDER *prov, | |
18 | void *method_data), | |
19 | void *method_data, | |
7c95390e | 20 | int (*up_ref_method)(void *), |
0211740f | 21 | void (*free_method)(void *)); |
c13d2ab4 | 22 | |
2fd3392c RL |
23 | void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, |
24 | int name_id, const char *properties, | |
25 | void *(*new_method)(int name_id, | |
26 | const OSSL_DISPATCH *fns, | |
27 | OSSL_PROVIDER *prov, | |
28 | void *method_data), | |
29 | void *method_data, | |
30 | int (*up_ref_method)(void *), | |
31 | void (*free_method)(void *)); | |
f7c16d48 | 32 | |
c13d2ab4 RL |
33 | =head1 DESCRIPTION |
34 | ||
35 | evp_generic_fetch() calls ossl_method_construct() with the given | |
f7c16d48 | 36 | I<libctx>, I<operation_id>, I<name>, and I<properties> and uses |
c13d2ab4 | 37 | it to create an EVP method with the help of the functions |
f7c16d48 RL |
38 | I<new_method>, I<up_ref_method>, and I<free_method>. |
39 | ||
2fd3392c RL |
40 | evp_generic_fetch_from_prov() does the same thing as evp_generic_fetch(), |
41 | but limits the search of methods to the provider given with I<prov>. | |
42 | This is meant to be used when one method needs to fetch an associated | |
43 | method in the same provider. | |
44 | ||
f7c16d48 RL |
45 | The three functions I<new_method>, I<up_ref_method>, and |
46 | I<free_method> are supposed to: | |
c13d2ab4 RL |
47 | |
48 | =over 4 | |
49 | ||
50 | =item new_method() | |
51 | ||
52 | creates an internal method from function pointers found in the | |
f7c16d48 RL |
53 | dispatch table I<fns>, with name identity I<name_id>. |
54 | The provider I<prov> and I<method_data> are also passed to be used as | |
55 | new_method() sees fit. | |
c13d2ab4 | 56 | |
7c95390e | 57 | =item up_ref_method() |
c13d2ab4 RL |
58 | |
59 | increments the reference counter for the given method, if there is | |
60 | one. | |
61 | ||
62 | =item free_method() | |
63 | ||
64 | frees the given method. | |
65 | ||
66 | =back | |
67 | ||
68 | =head1 RETURN VALUES | |
69 | ||
dfabee82 | 70 | evp_generic_fetch() returns a method on success, or NULL on error. |
c13d2ab4 RL |
71 | |
72 | =head1 EXAMPLES | |
73 | ||
74 | This is a short example of the fictitious EVP API and operation called | |
f7c16d48 | 75 | B<EVP_FOO>. |
c13d2ab4 RL |
76 | |
77 | To begin with, let's assume something like this in | |
23c48d94 | 78 | F<include/openssl/core_dispatch.h>: |
c13d2ab4 | 79 | |
363b1e5d DMSP |
80 | #define OSSL_OP_FOO 100 |
81 | ||
82 | #define OSSL_FUNC_FOO_NEWCTX_FUNC 2001 | |
83 | #define OSSL_FUNC_FOO_INIT 2002 | |
84 | #define OSSL_FUNC_FOO_OPERATE 2003 | |
85 | #define OSSL_FUNC_FOO_CLEANCTX_FUNC 2004 | |
86 | #define OSSL_FUNC_FOO_FREECTX_FUNC 2005 | |
87 | ||
88 | OSSL_CORE_MAKE_FUNC(void *, foo_newctx, (void)) | |
89 | OSSL_CORE_MAKE_FUNC(int, foo_init, (void *vctx)) | |
90 | OSSL_CORE_MAKE_FUNC(int, foo_operate, (void *vctx, | |
91 | unsigned char *out, size_t *out_l, | |
92 | unsigned char *in, size_t in_l)) | |
93 | OSSL_CORE_MAKE_FUNC(void, foo_cleanctx, (void *vctx)) | |
94 | OSSL_CORE_MAKE_FUNC(void, foo_freectx, (void *vctx)) | |
c13d2ab4 RL |
95 | |
96 | And here's the implementation of the FOO method fetcher: | |
97 | ||
98 | /* typedef struct evp_foo_st EVP_FOO */ | |
99 | struct evp_foo_st { | |
100 | OSSL_PROVIDER *prov; | |
f7c16d48 | 101 | int name_id; |
c13d2ab4 | 102 | CRYPTO_REF_COUNT refcnt; |
363b1e5d DMSP |
103 | OSSL_FUNC_foo_newctx_fn *newctx; |
104 | OSSL_FUNC_foo_init_fn *init; | |
105 | OSSL_FUNC_foo_operate_fn *operate; | |
106 | OSSL_FUNC_foo_cleanctx_fn *cleanctx; | |
107 | OSSL_FUNC_foo_freectx_fn *freectx; | |
c13d2ab4 RL |
108 | }; |
109 | ||
110 | /* | |
111 | * In this example, we have a public method creator and destructor. | |
112 | * It's not absolutely necessary, but is in the spirit of OpenSSL. | |
113 | */ | |
309a78aa RL |
114 | EVP_FOO *EVP_FOO_meth_from_algorithm(int name_id, |
115 | const OSSL_DISPATCH *fns, | |
116 | OSSL_PROVIDER *prov, | |
117 | void *data) | |
c13d2ab4 RL |
118 | { |
119 | EVP_FOO *foo = NULL; | |
120 | ||
121 | if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL) | |
122 | return NULL; | |
123 | ||
00fbc969 FWH |
124 | if (!CRYPTO_NEW_REF(&foo->refcnt, 1)) |
125 | goto err; | |
52c362b3 | 126 | |
f7c16d48 RL |
127 | foo->name_id = name_id; |
128 | ||
c13d2ab4 RL |
129 | for (; fns->function_id != 0; fns++) { |
130 | switch (fns->function_id) { | |
363b1e5d DMSP |
131 | case OSSL_FUNC_FOO_NEWCTX: |
132 | foo->newctx = OSSL_FUNC_foo_newctx(fns); | |
c13d2ab4 | 133 | break; |
363b1e5d DMSP |
134 | case OSSL_FUNC_FOO_INIT: |
135 | foo->init = OSSL_FUNC_foo_init(fns); | |
c13d2ab4 | 136 | break; |
363b1e5d DMSP |
137 | case OSSL_FUNC_FOO_OPERATE: |
138 | foo->operate = OSSL_FUNC_foo_operate(fns); | |
c13d2ab4 | 139 | break; |
363b1e5d DMSP |
140 | case OSSL_FUNC_FOO_CLEANCTX: |
141 | foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns); | |
c13d2ab4 | 142 | break; |
363b1e5d DMSP |
143 | case OSSL_FUNC_FOO_FREECTX: |
144 | foo->freectx = OSSL_FUNC_foo_freectx(fns); | |
c13d2ab4 RL |
145 | break; |
146 | } | |
147 | } | |
00fbc969 FWH |
148 | if (prov != NULL && !ossl_provider_up_ref(prov)) |
149 | goto err; | |
150 | ||
c13d2ab4 | 151 | foo->prov = prov; |
c13d2ab4 RL |
152 | |
153 | return foo; | |
00fbc969 FWH |
154 | |
155 | err: | |
156 | if (foo != NULL) | |
157 | CRYPTO_FREE_REF(&foo->refcnt); | |
158 | OPENSSL_free(foo); | |
159 | return NULL | |
c13d2ab4 RL |
160 | } |
161 | ||
162 | EVP_FOO_meth_free(EVP_FOO *foo) | |
163 | { | |
52c362b3 P |
164 | int i; |
165 | ||
c13d2ab4 RL |
166 | if (foo != NULL) { |
167 | OSSL_PROVIDER *prov = foo->prov; | |
168 | ||
52c362b3 P |
169 | CRYPTO_DOWN_REF(&foo->refcnt, &i); |
170 | if (i > 0) | |
171 | return; | |
172 | ||
173 | CRYPTO_FREE_REF(&foo->refcnt); | |
c13d2ab4 RL |
174 | OPENSSL_free(foo); |
175 | ossl_provider_free(prov); | |
176 | } | |
177 | } | |
178 | ||
309a78aa RL |
179 | static void *foo_from_algorithm(const OSSL_DISPATCH *fns, |
180 | OSSL_PROVIDER *prov) | |
c13d2ab4 | 181 | { |
309a78aa | 182 | return EVP_FOO_meth_from_algorithm(fns, prov); |
c13d2ab4 RL |
183 | } |
184 | ||
7c95390e | 185 | static int foo_up_ref(void *vfoo) |
c13d2ab4 RL |
186 | { |
187 | EVP_FOO *foo = vfoo; | |
188 | int ref = 0; | |
189 | ||
52c362b3 | 190 | CRYPTO_UP_REF(&foo->refcnt, &ref); |
c13d2ab4 RL |
191 | return 1; |
192 | } | |
193 | ||
194 | static void foo_free(void *vfoo) | |
195 | { | |
196 | EVP_FOO_meth_free(vfoo); | |
197 | } | |
198 | ||
b4250010 | 199 | EVP_FOO *EVP_FOO_fetch(OSSL_LIB_CTX *ctx, |
2e49c054 | 200 | const char *name, |
c13d2ab4 RL |
201 | const char *properties) |
202 | { | |
0211740f RL |
203 | EVP_FOO *foo = |
204 | evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties, | |
309a78aa | 205 | foo_from_algorithm, foo_up_ref, foo_free); |
0211740f RL |
206 | |
207 | /* | |
208 | * If this method exists in legacy form, with a constant NID for the | |
209 | * given |name|, this is the spot to find that NID and set it in | |
210 | * the newly constructed EVP_FOO instance. | |
211 | */ | |
212 | ||
213 | return foo; | |
214 | ||
c13d2ab4 RL |
215 | } |
216 | ||
217 | And finally, the library functions: | |
218 | ||
219 | /* typedef struct evp_foo_st EVP_FOO_CTX */ | |
220 | struct evp_foo_ctx_st { | |
221 | const EVP_FOO *foo; | |
222 | void *provctx; /* corresponding provider context */ | |
223 | }; | |
224 | ||
225 | int EVP_FOO_CTX_reset(EVP_FOO_CTX *c) | |
226 | { | |
227 | if (c == NULL) | |
228 | return 1; | |
229 | if (c->foo != NULL && c->foo->cleanctx != NULL) | |
230 | c->foo->cleanctx(c->provctx); | |
231 | return 1; | |
232 | } | |
233 | ||
234 | EVP_FOO_CTX *EVP_FOO_CTX_new(void) | |
235 | { | |
236 | return OPENSSL_zalloc(sizeof(EVP_FOO_CTX)); | |
237 | } | |
238 | ||
239 | void EVP_FOO_CTX_free(EVP_FOO_CTX *c) | |
240 | { | |
241 | EVP_FOO_CTX_reset(c); | |
242 | c->foo->freectx(c->provctx); | |
243 | OPENSSL_free(c); | |
244 | } | |
245 | ||
246 | int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo) | |
247 | { | |
248 | int ok = 1; | |
249 | ||
250 | c->foo = foo; | |
251 | if (c->provctx == NULL) | |
252 | c->provctx = c->foo->newctx(); | |
253 | ||
254 | ok = c->foo->init(c->provctx); | |
255 | ||
256 | return ok; | |
257 | } | |
258 | ||
259 | int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl, | |
260 | const unsigned char *in, size_t inl) | |
261 | { | |
262 | int ok = 1; | |
263 | ||
264 | ok = c->foo->update(c->provctx, out, inl, &outl, in, inl); | |
265 | return ok; | |
266 | } | |
267 | ||
268 | =head1 SEE ALSO | |
269 | ||
6e4618a0 | 270 | L<ossl_method_construct(3)> |
c13d2ab4 RL |
271 | |
272 | =head1 HISTORY | |
273 | ||
274 | The functions described here were all added in OpenSSL 3.0. | |
275 | ||
276 | =head1 COPYRIGHT | |
277 | ||
0c679f55 | 278 | Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. |
c13d2ab4 RL |
279 | |
280 | Licensed under the Apache License 2.0 (the "License"). You may not use | |
281 | this file except in compliance with the License. You can obtain a copy | |
282 | in the file LICENSE in the source distribution or at | |
283 | L<https://www.openssl.org/source/license.html>. | |
284 | ||
285 | =cut |