]>
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 | ||
52c362b3 P |
124 | if (!CRYPTO_NEW_REF(&foo->refcnt, 1)) { |
125 | OPENSSL_free(foo); | |
126 | return NULL; | |
127 | } | |
128 | ||
f7c16d48 RL |
129 | foo->name_id = name_id; |
130 | ||
c13d2ab4 RL |
131 | for (; fns->function_id != 0; fns++) { |
132 | switch (fns->function_id) { | |
363b1e5d DMSP |
133 | case OSSL_FUNC_FOO_NEWCTX: |
134 | foo->newctx = OSSL_FUNC_foo_newctx(fns); | |
c13d2ab4 | 135 | break; |
363b1e5d DMSP |
136 | case OSSL_FUNC_FOO_INIT: |
137 | foo->init = OSSL_FUNC_foo_init(fns); | |
c13d2ab4 | 138 | break; |
363b1e5d DMSP |
139 | case OSSL_FUNC_FOO_OPERATE: |
140 | foo->operate = OSSL_FUNC_foo_operate(fns); | |
c13d2ab4 | 141 | break; |
363b1e5d DMSP |
142 | case OSSL_FUNC_FOO_CLEANCTX: |
143 | foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns); | |
c13d2ab4 | 144 | break; |
363b1e5d DMSP |
145 | case OSSL_FUNC_FOO_FREECTX: |
146 | foo->freectx = OSSL_FUNC_foo_freectx(fns); | |
c13d2ab4 RL |
147 | break; |
148 | } | |
149 | } | |
c13d2ab4 RL |
150 | foo->prov = prov; |
151 | if (prov) | |
7c95390e | 152 | ossl_provider_up_ref(prov); |
c13d2ab4 RL |
153 | |
154 | return foo; | |
155 | } | |
156 | ||
157 | EVP_FOO_meth_free(EVP_FOO *foo) | |
158 | { | |
52c362b3 P |
159 | int i; |
160 | ||
c13d2ab4 RL |
161 | if (foo != NULL) { |
162 | OSSL_PROVIDER *prov = foo->prov; | |
163 | ||
52c362b3 P |
164 | CRYPTO_DOWN_REF(&foo->refcnt, &i); |
165 | if (i > 0) | |
166 | return; | |
167 | ||
168 | CRYPTO_FREE_REF(&foo->refcnt); | |
c13d2ab4 RL |
169 | OPENSSL_free(foo); |
170 | ossl_provider_free(prov); | |
171 | } | |
172 | } | |
173 | ||
309a78aa RL |
174 | static void *foo_from_algorithm(const OSSL_DISPATCH *fns, |
175 | OSSL_PROVIDER *prov) | |
c13d2ab4 | 176 | { |
309a78aa | 177 | return EVP_FOO_meth_from_algorithm(fns, prov); |
c13d2ab4 RL |
178 | } |
179 | ||
7c95390e | 180 | static int foo_up_ref(void *vfoo) |
c13d2ab4 RL |
181 | { |
182 | EVP_FOO *foo = vfoo; | |
183 | int ref = 0; | |
184 | ||
52c362b3 | 185 | CRYPTO_UP_REF(&foo->refcnt, &ref); |
c13d2ab4 RL |
186 | return 1; |
187 | } | |
188 | ||
189 | static void foo_free(void *vfoo) | |
190 | { | |
191 | EVP_FOO_meth_free(vfoo); | |
192 | } | |
193 | ||
b4250010 | 194 | EVP_FOO *EVP_FOO_fetch(OSSL_LIB_CTX *ctx, |
2e49c054 | 195 | const char *name, |
c13d2ab4 RL |
196 | const char *properties) |
197 | { | |
0211740f RL |
198 | EVP_FOO *foo = |
199 | evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties, | |
309a78aa | 200 | foo_from_algorithm, foo_up_ref, foo_free); |
0211740f RL |
201 | |
202 | /* | |
203 | * If this method exists in legacy form, with a constant NID for the | |
204 | * given |name|, this is the spot to find that NID and set it in | |
205 | * the newly constructed EVP_FOO instance. | |
206 | */ | |
207 | ||
208 | return foo; | |
209 | ||
c13d2ab4 RL |
210 | } |
211 | ||
212 | And finally, the library functions: | |
213 | ||
214 | /* typedef struct evp_foo_st EVP_FOO_CTX */ | |
215 | struct evp_foo_ctx_st { | |
216 | const EVP_FOO *foo; | |
217 | void *provctx; /* corresponding provider context */ | |
218 | }; | |
219 | ||
220 | int EVP_FOO_CTX_reset(EVP_FOO_CTX *c) | |
221 | { | |
222 | if (c == NULL) | |
223 | return 1; | |
224 | if (c->foo != NULL && c->foo->cleanctx != NULL) | |
225 | c->foo->cleanctx(c->provctx); | |
226 | return 1; | |
227 | } | |
228 | ||
229 | EVP_FOO_CTX *EVP_FOO_CTX_new(void) | |
230 | { | |
231 | return OPENSSL_zalloc(sizeof(EVP_FOO_CTX)); | |
232 | } | |
233 | ||
234 | void EVP_FOO_CTX_free(EVP_FOO_CTX *c) | |
235 | { | |
236 | EVP_FOO_CTX_reset(c); | |
237 | c->foo->freectx(c->provctx); | |
238 | OPENSSL_free(c); | |
239 | } | |
240 | ||
241 | int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo) | |
242 | { | |
243 | int ok = 1; | |
244 | ||
245 | c->foo = foo; | |
246 | if (c->provctx == NULL) | |
247 | c->provctx = c->foo->newctx(); | |
248 | ||
249 | ok = c->foo->init(c->provctx); | |
250 | ||
251 | return ok; | |
252 | } | |
253 | ||
254 | int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl, | |
255 | const unsigned char *in, size_t inl) | |
256 | { | |
257 | int ok = 1; | |
258 | ||
259 | ok = c->foo->update(c->provctx, out, inl, &outl, in, inl); | |
260 | return ok; | |
261 | } | |
262 | ||
263 | =head1 SEE ALSO | |
264 | ||
6e4618a0 | 265 | L<ossl_method_construct(3)> |
c13d2ab4 RL |
266 | |
267 | =head1 HISTORY | |
268 | ||
269 | The functions described here were all added in OpenSSL 3.0. | |
270 | ||
271 | =head1 COPYRIGHT | |
272 | ||
da1c088f | 273 | Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. |
c13d2ab4 RL |
274 | |
275 | Licensed under the Apache License 2.0 (the "License"). You may not use | |
276 | this file except in compliance with the License. You can obtain a copy | |
277 | in the file LICENSE in the source distribution or at | |
278 | L<https://www.openssl.org/source/license.html>. | |
279 | ||
280 | =cut |