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