Refactor how KEYMGMT methods get associated with other methods
[openssl.git] / doc / internal / man3 / evp_generic_fetch.pod
1 =pod
2
3 =head1 NAME
4
5 evp_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,
13                          const char *name, const char *properties,
14                          void *(*new_method)(const char *name,
15                                              const OSSL_DISPATCH *fns,
16                                              OSSL_PROVIDER *prov,
17                                              void *method_data),
18                          void *method_data,
19                          int (*up_ref_method)(void *),
20                          void (*free_method)(void *));
21
22 =head1 DESCRIPTION
23
24 evp_generic_fetch() calls ossl_method_construct() with the given
25 C<libctx>, C<operation_id>, C<name>, and C<properties> and uses
26 it to create an EVP method with the help of the functions
27 C<new_method>, C<up_ref_method>, and C<free_method>.
28
29 The three functions are supposed to:
30
31 =over 4
32
33 =item new_method()
34
35 creates an internal method from function pointers found in the
36 dispatch table C<fns>.
37 The algorithm I<name>, provider I<prov>, and I<method_data> are
38 also passed to be used as new_method() sees fit.
39
40 =item up_ref_method()
41
42 increments the reference counter for the given method, if there is
43 one.
44
45 =item free_method()
46
47 frees the given method.
48
49 =back
50
51 =head1 RETURN VALUES
52
53 evp_generic_fetch() returns a method on success, or B<NULL> on error.
54
55 =head1 EXAMPLES
56
57 This is a short example of the fictitious EVP API and operation called
58 C<EVP_FOO>.
59
60 To begin with, let's assume something like this in
61 C<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
78 And 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;
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      */
95     EVP_FOO *EVP_FOO_meth_from_dispatch(const OSSL_DISPATCH *fns,
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         }
122         foo->prov = prov;
123         if (prov)
124             ossl_provider_up_ref(prov);
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
139     static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
140                                    OSSL_PROVIDER *prov)
141     {
142         return EVP_FOO_meth_from_dispatch(fns, prov);
143     }
144
145     static int foo_up_ref(void *vfoo)
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,
160                            const char *name,
161                            const char *properties)
162     {
163         EVP_FOO *foo =
164             evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
165                               foo_from_dispatch, foo_up_ref, foo_free);
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
175     }
176
177 And 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
230 L<ossl_method_construct>
231
232 =head1 HISTORY
233
234 The functions described here were all added in OpenSSL 3.0.
235
236 =head1 COPYRIGHT
237
238 Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
239
240 Licensed under the Apache License 2.0 (the "License").  You may not use
241 this file except in compliance with the License.  You can obtain a copy
242 in the file LICENSE in the source distribution or at
243 L<https://www.openssl.org/source/license.html>.
244
245 =cut