Fix up path generation to use OPENSSL_MODULES
[openssl.git] / doc / internal / man3 / evp_generic_fetch.pod
1 =pod
2
3 =head1 NAME
4
5 evp_generic_fetch, evp_generic_fetch_by_number
6 - generic algorithm fetchers and method creators for EVP
7
8 =head1 SYNOPSIS
9
10  /* Only for EVP source */
11  #include "evp_local.h"
12
13  void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
14                          const char *name, const char *properties,
15                          void *(*new_method)(int name_id,
16                                              const OSSL_DISPATCH *fns,
17                                              OSSL_PROVIDER *prov,
18                                              void *method_data),
19                          void *method_data,
20                          int (*up_ref_method)(void *),
21                          void (*free_method)(void *));
22
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
33 =head1 DESCRIPTION
34
35 evp_generic_fetch() calls ossl_method_construct() with the given
36 I<libctx>, I<operation_id>, I<name>, and I<properties> and uses
37 it to create an EVP method with the help of the functions
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 numeric I<name_id> instead of a name.
42 I<name_id> must always be nonzero; 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>.
47
48 The three functions I<new_method>, I<up_ref_method>, and
49 I<free_method> are supposed to:
50
51 =over 4
52
53 =item new_method()
54
55 creates an internal method from function pointers found in the
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.
59
60 =item up_ref_method()
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
73 evp_generic_fetch() returns a method on success, or NULL on error.
74
75 =head1 EXAMPLES
76
77 This is a short example of the fictitious EVP API and operation called
78 B<EVP_FOO>.
79
80 To begin with, let's assume something like this in
81 F<include/openssl/core_dispatch.h>:
82
83     #define OSSL_OP_FOO                           100
84
85     #define OSSL_FUNC_FOO_NEWCTX_FUNC            2001
86     #define OSSL_FUNC_FOO_INIT                   2002
87     #define OSSL_FUNC_FOO_OPERATE                2003
88     #define OSSL_FUNC_FOO_CLEANCTX_FUNC          2004
89     #define OSSL_FUNC_FOO_FREECTX_FUNC           2005
90
91     OSSL_CORE_MAKE_FUNC(void *, foo_newctx, (void))
92     OSSL_CORE_MAKE_FUNC(int, foo_init, (void *vctx))
93     OSSL_CORE_MAKE_FUNC(int, foo_operate, (void *vctx,
94                                            unsigned char *out, size_t *out_l,
95                                            unsigned char *in, size_t in_l))
96     OSSL_CORE_MAKE_FUNC(void, foo_cleanctx, (void *vctx))
97     OSSL_CORE_MAKE_FUNC(void, foo_freectx, (void *vctx))
98
99 And here's the implementation of the FOO method fetcher:
100
101     /* typedef struct evp_foo_st EVP_FOO */
102     struct evp_foo_st {
103         OSSL_PROVIDER *prov;
104         int name_id;
105         CRYPTO_REF_COUNT refcnt;
106         OSSL_FUNC_foo_newctx_fn *newctx;
107         OSSL_FUNC_foo_init_fn *init;
108         OSSL_FUNC_foo_operate_fn *operate;
109         OSSL_FUNC_foo_cleanctx_fn *cleanctx;
110         OSSL_FUNC_foo_freectx_fn *freectx;
111     };
112
113     /*
114      * In this example, we have a public method creator and destructor.
115      * It's not absolutely necessary, but is in the spirit of OpenSSL.
116      */
117     EVP_FOO *EVP_FOO_meth_from_dispatch(int name_id,
118                                         const OSSL_DISPATCH *fns,
119                                         OSSL_PROVIDER *prov,
120                                         void *data)
121     {
122         EVP_FOO *foo = NULL;
123
124         if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
125             return NULL;
126
127         foo->name_id = name_id;
128
129         for (; fns->function_id != 0; fns++) {
130             switch (fns->function_id) {
131             case OSSL_FUNC_FOO_NEWCTX:
132                 foo->newctx = OSSL_FUNC_foo_newctx(fns);
133                 break;
134             case OSSL_FUNC_FOO_INIT:
135                 foo->init = OSSL_FUNC_foo_init(fns);
136                 break;
137             case OSSL_FUNC_FOO_OPERATE:
138                 foo->operate = OSSL_FUNC_foo_operate(fns);
139                 break;
140             case OSSL_FUNC_FOO_CLEANCTX:
141                 foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns);
142                 break;
143             case OSSL_FUNC_FOO_FREECTX:
144                 foo->freectx = OSSL_FUNC_foo_freectx(fns);
145                 break;
146             }
147         }
148         foo->prov = prov;
149         if (prov)
150             ossl_provider_up_ref(prov);
151
152         return foo;
153     }
154
155     EVP_FOO_meth_free(EVP_FOO *foo)
156     {
157         if (foo != NULL) {
158             OSSL_PROVIDER *prov = foo->prov;
159
160             OPENSSL_free(foo);
161             ossl_provider_free(prov);
162         }
163     }
164
165     static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
166                                    OSSL_PROVIDER *prov)
167     {
168         return EVP_FOO_meth_from_dispatch(fns, prov);
169     }
170
171     static int foo_up_ref(void *vfoo)
172     {
173         EVP_FOO *foo = vfoo;
174         int ref = 0;
175
176         CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
177         return 1;
178     }
179
180     static void foo_free(void *vfoo)
181     {
182         EVP_FOO_meth_free(vfoo);
183     }
184
185     EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx,
186                            const char *name,
187                            const char *properties)
188     {
189         EVP_FOO *foo =
190             evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
191                               foo_from_dispatch, foo_up_ref, foo_free);
192
193         /*
194          * If this method exists in legacy form, with a constant NID for the
195          * given |name|, this is the spot to find that NID and set it in
196          * the newly constructed EVP_FOO instance.
197          */
198
199         return foo;
200
201     }
202
203 And finally, the library functions:
204
205     /* typedef struct evp_foo_st EVP_FOO_CTX */
206     struct evp_foo_ctx_st {
207         const EVP_FOO *foo;
208         void *provctx;          /* corresponding provider context */
209     };
210
211     int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
212     {
213         if (c == NULL)
214             return 1;
215         if (c->foo != NULL && c->foo->cleanctx != NULL)
216             c->foo->cleanctx(c->provctx);
217         return 1;
218     }
219
220     EVP_FOO_CTX *EVP_FOO_CTX_new(void)
221     {
222         return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
223     }
224
225     void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
226     {
227         EVP_FOO_CTX_reset(c);
228         c->foo->freectx(c->provctx);
229         OPENSSL_free(c);
230     }
231
232     int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
233     {
234         int ok = 1;
235
236         c->foo = foo;
237         if (c->provctx == NULL)
238             c->provctx = c->foo->newctx();
239
240         ok = c->foo->init(c->provctx);
241
242         return ok;
243     }
244
245     int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
246                        const unsigned char *in, size_t inl)
247     {
248         int ok = 1;
249
250         ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
251         return ok;
252     }
253
254 =head1 SEE ALSO
255
256 L<ossl_method_construct(3)>
257
258 =head1 HISTORY
259
260 The functions described here were all added in OpenSSL 3.0.
261
262 =head1 COPYRIGHT
263
264 Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
265
266 Licensed under the Apache License 2.0 (the "License").  You may not use
267 this file except in compliance with the License.  You can obtain a copy
268 in the file LICENSE in the source distribution or at
269 L<https://www.openssl.org/source/license.html>.
270
271 =cut