]> git.ipfire.org Git - thirdparty/openssl.git/blame - doc/internal/man3/evp_generic_fetch.pod
apps: avoid memory overrun.
[thirdparty/openssl.git] / doc / internal / man3 / evp_generic_fetch.pod
CommitLineData
c13d2ab4
RL
1=pod
2
3=head1 NAME
4
f7c16d48
RL
5evp_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
35evp_generic_fetch() calls ossl_method_construct() with the given
f7c16d48 36I<libctx>, I<operation_id>, I<name>, and I<properties> and uses
c13d2ab4 37it to create an EVP method with the help of the functions
f7c16d48
RL
38I<new_method>, I<up_ref_method>, and I<free_method>.
39
40evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(),
41but takes a I<name_id> instead of a number.
9c0586d5 42I<name_id> must always be nonzero; as a matter of fact, it being zero
f7c16d48
RL
43is considered a programming error.
44This is meant to be used when one method needs to fetch an associated
45other method, and is typically called from inside the given function
46I<new_method>.
c13d2ab4 47
f7c16d48
RL
48The three functions I<new_method>, I<up_ref_method>, and
49I<free_method> are supposed to:
c13d2ab4
RL
50
51=over 4
52
53=item new_method()
54
55creates an internal method from function pointers found in the
f7c16d48
RL
56dispatch table I<fns>, with name identity I<name_id>.
57The provider I<prov> and I<method_data> are also passed to be used as
58new_method() sees fit.
c13d2ab4 59
7c95390e 60=item up_ref_method()
c13d2ab4
RL
61
62increments the reference counter for the given method, if there is
63one.
64
65=item free_method()
66
67frees the given method.
68
69=back
70
71=head1 RETURN VALUES
72
dfabee82 73evp_generic_fetch() returns a method on success, or NULL on error.
c13d2ab4
RL
74
75=head1 EXAMPLES
76
77This is a short example of the fictitious EVP API and operation called
f7c16d48 78B<EVP_FOO>.
c13d2ab4
RL
79
80To begin with, let's assume something like this in
f7c16d48 81F<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
98And 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
202And 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
6e4618a0 255L<ossl_method_construct(3)>
c13d2ab4
RL
256
257=head1 HISTORY
258
259The functions described here were all added in OpenSSL 3.0.
260
261=head1 COPYRIGHT
262
263Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
264
265Licensed under the Apache License 2.0 (the "License"). You may not use
266this file except in compliance with the License. You can obtain a copy
267in the file LICENSE in the source distribution or at
268L<https://www.openssl.org/source/license.html>.
269
270=cut