]>
Commit | Line | Data |
---|---|---|
c13d2ab4 RL |
1 | =pod |
2 | ||
3 | =head1 NAME | |
4 | ||
f7c16d48 RL |
5 | evp_generic_fetch, evp_generic_fetch_by_number |
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 RL |
12 | |
13 | void *evp_generic_fetch(OPENSSL_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 | |
f7c16d48 RL |
23 | void *evp_generic_fetch_by_number(OPENSSL_CTX *ctx, 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 *)); | |
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 | ||
40 | evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(), | |
41 | but takes a I<name_id> instead of a number. | |
42 | I<name_id> must always be non-zero; as a matter of fact, it being zero | |
43 | is considered a programming error. | |
44 | This is meant to be used when one method needs to fetch an associated | |
45 | other method, and is typically called from inside the given function | |
46 | I<new_method>. | |
c13d2ab4 | 47 | |
f7c16d48 RL |
48 | The three functions I<new_method>, I<up_ref_method>, and |
49 | I<free_method> are supposed to: | |
c13d2ab4 RL |
50 | |
51 | =over 4 | |
52 | ||
53 | =item new_method() | |
54 | ||
55 | creates an internal method from function pointers found in the | |
f7c16d48 RL |
56 | dispatch table I<fns>, with name identity I<name_id>. |
57 | The provider I<prov> and I<method_data> are also passed to be used as | |
58 | new_method() sees fit. | |
c13d2ab4 | 59 | |
7c95390e | 60 | =item up_ref_method() |
c13d2ab4 RL |
61 | |
62 | increments the reference counter for the given method, if there is | |
63 | one. | |
64 | ||
65 | =item free_method() | |
66 | ||
67 | frees the given method. | |
68 | ||
69 | =back | |
70 | ||
71 | =head1 RETURN VALUES | |
72 | ||
dfabee82 | 73 | evp_generic_fetch() returns a method on success, or NULL on error. |
c13d2ab4 RL |
74 | |
75 | =head1 EXAMPLES | |
76 | ||
77 | This is a short example of the fictitious EVP API and operation called | |
f7c16d48 | 78 | B<EVP_FOO>. |
c13d2ab4 RL |
79 | |
80 | To begin with, let's assume something like this in | |
f7c16d48 | 81 | F<include/openssl/core_numbers.h>: |
c13d2ab4 RL |
82 | |
83 | #define OSSL_OP_FOO 100 | |
84 | ||
85 | #define OSSL_OP_FOO_NEWCTX_FUNC 2001 | |
86 | #define OSSL_OP_FOO_INIT 2002 | |
87 | #define OSSL_OP_FOO_OPERATE 2003 | |
88 | #define OSSL_OP_FOO_CLEANCTX_FUNC 2004 | |
89 | #define OSSL_OP_FOO_FREECTX_FUNC 2005 | |
90 | OSSL_CORE_MAKE_FUNC(void *,OP_foo_newctx,(void)) | |
91 | OSSL_CORE_MAKE_FUNC(int,OP_foo_init,(void *vctx)) | |
92 | OSSL_CORE_MAKE_FUNC(int,OP_foo_operate,(void *vctx, | |
93 | unsigned char *out, size_t *out_l, | |
94 | unsigned char *in, size_t in_l)) | |
95 | OSSL_CORE_MAKE_FUNC(void,OP_foo_cleanctx,(void *vctx)) | |
96 | OSSL_CORE_MAKE_FUNC(void,OP_foo_freectx,(void *vctx)) | |
97 | ||
98 | And here's the implementation of the FOO method fetcher: | |
99 | ||
100 | /* typedef struct evp_foo_st EVP_FOO */ | |
101 | struct evp_foo_st { | |
102 | OSSL_PROVIDER *prov; | |
f7c16d48 | 103 | int name_id; |
c13d2ab4 RL |
104 | CRYPTO_REF_COUNT refcnt; |
105 | OSSL_OP_foo_newctx_fn *newctx; | |
106 | OSSL_OP_foo_init_fn *init; | |
107 | OSSL_OP_foo_operate_fn *operate; | |
108 | OSSL_OP_foo_cleanctx_fn *cleanctx; | |
109 | OSSL_OP_foo_freectx_fn *freectx; | |
110 | }; | |
111 | ||
112 | /* | |
113 | * In this example, we have a public method creator and destructor. | |
114 | * It's not absolutely necessary, but is in the spirit of OpenSSL. | |
115 | */ | |
f7c16d48 RL |
116 | EVP_FOO *EVP_FOO_meth_from_dispatch(int name_id, |
117 | const OSSL_DISPATCH *fns, | |
118 | OSSL_PROVIDER *prov, | |
119 | void *data) | |
c13d2ab4 RL |
120 | { |
121 | EVP_FOO *foo = NULL; | |
122 | ||
123 | if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL) | |
124 | return NULL; | |
125 | ||
f7c16d48 RL |
126 | foo->name_id = name_id; |
127 | ||
c13d2ab4 RL |
128 | for (; fns->function_id != 0; fns++) { |
129 | switch (fns->function_id) { | |
130 | case OSSL_OP_FOO_NEWCTX_FUNC: | |
131 | foo->newctx = OSSL_get_OP_foo_newctx(fns); | |
132 | break; | |
133 | case OSSL_OP_FOO_INIT: | |
134 | foo->init = OSSL_get_OP_foo_init(fns); | |
135 | break; | |
136 | case OSSL_OP_FOO_OPERATE: | |
137 | foo->operate = OSSL_get_OP_foo_operate(fns); | |
138 | break; | |
139 | case OSSL_OP_FOO_CLEANCTX_FUNC: | |
140 | foo->cleanctx = OSSL_get_OP_foo_cleanctx(fns); | |
141 | break; | |
142 | case OSSL_OP_FOO_FREECTX_FUNC: | |
143 | foo->freectx = OSSL_get_OP_foo_freectx(fns); | |
144 | break; | |
145 | } | |
146 | } | |
c13d2ab4 RL |
147 | foo->prov = prov; |
148 | if (prov) | |
7c95390e | 149 | ossl_provider_up_ref(prov); |
c13d2ab4 RL |
150 | |
151 | return foo; | |
152 | } | |
153 | ||
154 | EVP_FOO_meth_free(EVP_FOO *foo) | |
155 | { | |
156 | if (foo != NULL) { | |
157 | OSSL_PROVIDER *prov = foo->prov; | |
158 | ||
159 | OPENSSL_free(foo); | |
160 | ossl_provider_free(prov); | |
161 | } | |
162 | } | |
163 | ||
0211740f | 164 | static void *foo_from_dispatch(const OSSL_DISPATCH *fns, |
c13d2ab4 RL |
165 | OSSL_PROVIDER *prov) |
166 | { | |
0211740f | 167 | return EVP_FOO_meth_from_dispatch(fns, prov); |
c13d2ab4 RL |
168 | } |
169 | ||
7c95390e | 170 | static int foo_up_ref(void *vfoo) |
c13d2ab4 RL |
171 | { |
172 | EVP_FOO *foo = vfoo; | |
173 | int ref = 0; | |
174 | ||
175 | CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock); | |
176 | return 1; | |
177 | } | |
178 | ||
179 | static void foo_free(void *vfoo) | |
180 | { | |
181 | EVP_FOO_meth_free(vfoo); | |
182 | } | |
183 | ||
184 | EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx, | |
2e49c054 | 185 | const char *name, |
c13d2ab4 RL |
186 | const char *properties) |
187 | { | |
0211740f RL |
188 | EVP_FOO *foo = |
189 | evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties, | |
7c95390e | 190 | foo_from_dispatch, foo_up_ref, foo_free); |
0211740f RL |
191 | |
192 | /* | |
193 | * If this method exists in legacy form, with a constant NID for the | |
194 | * given |name|, this is the spot to find that NID and set it in | |
195 | * the newly constructed EVP_FOO instance. | |
196 | */ | |
197 | ||
198 | return foo; | |
199 | ||
c13d2ab4 RL |
200 | } |
201 | ||
202 | And finally, the library functions: | |
203 | ||
204 | /* typedef struct evp_foo_st EVP_FOO_CTX */ | |
205 | struct evp_foo_ctx_st { | |
206 | const EVP_FOO *foo; | |
207 | void *provctx; /* corresponding provider context */ | |
208 | }; | |
209 | ||
210 | int EVP_FOO_CTX_reset(EVP_FOO_CTX *c) | |
211 | { | |
212 | if (c == NULL) | |
213 | return 1; | |
214 | if (c->foo != NULL && c->foo->cleanctx != NULL) | |
215 | c->foo->cleanctx(c->provctx); | |
216 | return 1; | |
217 | } | |
218 | ||
219 | EVP_FOO_CTX *EVP_FOO_CTX_new(void) | |
220 | { | |
221 | return OPENSSL_zalloc(sizeof(EVP_FOO_CTX)); | |
222 | } | |
223 | ||
224 | void EVP_FOO_CTX_free(EVP_FOO_CTX *c) | |
225 | { | |
226 | EVP_FOO_CTX_reset(c); | |
227 | c->foo->freectx(c->provctx); | |
228 | OPENSSL_free(c); | |
229 | } | |
230 | ||
231 | int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo) | |
232 | { | |
233 | int ok = 1; | |
234 | ||
235 | c->foo = foo; | |
236 | if (c->provctx == NULL) | |
237 | c->provctx = c->foo->newctx(); | |
238 | ||
239 | ok = c->foo->init(c->provctx); | |
240 | ||
241 | return ok; | |
242 | } | |
243 | ||
244 | int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl, | |
245 | const unsigned char *in, size_t inl) | |
246 | { | |
247 | int ok = 1; | |
248 | ||
249 | ok = c->foo->update(c->provctx, out, inl, &outl, in, inl); | |
250 | return ok; | |
251 | } | |
252 | ||
253 | =head1 SEE ALSO | |
254 | ||
255 | L<ossl_method_construct> | |
256 | ||
257 | =head1 HISTORY | |
258 | ||
259 | The functions described here were all added in OpenSSL 3.0. | |
260 | ||
261 | =head1 COPYRIGHT | |
262 | ||
263 | Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
264 | ||
265 | Licensed under the Apache License 2.0 (the "License"). You may not use | |
266 | this file except in compliance with the License. You can obtain a copy | |
267 | in the file LICENSE in the source distribution or at | |
268 | L<https://www.openssl.org/source/license.html>. | |
269 | ||
270 | =cut |