4cff97def81c1f76ee87967e04a46e075544a22d
[oweals/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 I<name_id> instead of a number.
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_numbers.h>:
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;
103         int name_id;
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      */
116     EVP_FOO *EVP_FOO_meth_from_dispatch(int name_id,
117                                         const OSSL_DISPATCH *fns,
118                                         OSSL_PROVIDER *prov,
119                                         void *data)
120     {
121         EVP_FOO *foo = NULL;
122
123         if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
124             return NULL;
125
126         foo->name_id = name_id;
127
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         }
147         foo->prov = prov;
148         if (prov)
149             ossl_provider_up_ref(prov);
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
164     static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
165                                    OSSL_PROVIDER *prov)
166     {
167         return EVP_FOO_meth_from_dispatch(fns, prov);
168     }
169
170     static int foo_up_ref(void *vfoo)
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,
185                            const char *name,
186                            const char *properties)
187     {
188         EVP_FOO *foo =
189             evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
190                               foo_from_dispatch, foo_up_ref, foo_free);
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
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(3)>
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