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