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