8b0f5425154aec8c1f4956cfc019f0106f2ce040
[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)(int nid, const OSSL_DISPATCH *fns,
15                                              OSSL_PROVIDER *prov),
16                          int (*upref_method)(void *),
17                          void (*free_method)(void *),
18                          int (*nid_method)(void *));
19
20 =head1 DESCRIPTION
21
22 evp_generic_fetch() calls ossl_method_construct() with the given
23 C<libctx>, C<operation_id>, C<name>, and C<properties> and uses
24 it to create an EVP method with the help of the functions
25 C<new_method>, C<upref_method>, and C<free_method>.
26
27 The three functions are supposed to:
28
29 =over 4
30
31 =item new_method()
32
33 creates an internal method from function pointers found in the
34 dispatch table C<fns>.
35
36 =item upref_method()
37
38 increments the reference counter for the given method, if there is
39 one.
40
41 =item free_method()
42
43 frees the given method.
44
45 =item nid_method()
46
47 returns the nid associated with 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         int nid;
84         CRYPTO_REF_COUNT refcnt;
85         OSSL_OP_foo_newctx_fn *newctx;
86         OSSL_OP_foo_init_fn *init;
87         OSSL_OP_foo_operate_fn *operate;
88         OSSL_OP_foo_cleanctx_fn *cleanctx;
89         OSSL_OP_foo_freectx_fn *freectx;
90     };
91
92     /*
93      * In this example, we have a public method creator and destructor.
94      * It's not absolutely necessary, but is in the spirit of OpenSSL.
95      */
96     EVP_FOO *EVP_FOO_meth_from_dispatch(int foo_type, const OSSL_DISPATCH *fns,
97                                         OSSL_PROVIDER *prov)
98     {
99         EVP_FOO *foo = NULL;
100
101         if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
102             return NULL;
103
104         for (; fns->function_id != 0; fns++) {
105             switch (fns->function_id) {
106             case OSSL_OP_FOO_NEWCTX_FUNC:
107                 foo->newctx = OSSL_get_OP_foo_newctx(fns);
108                 break;
109             case OSSL_OP_FOO_INIT:
110                 foo->init = OSSL_get_OP_foo_init(fns);
111                 break;
112             case OSSL_OP_FOO_OPERATE:
113                 foo->operate = OSSL_get_OP_foo_operate(fns);
114                 break;
115             case OSSL_OP_FOO_CLEANCTX_FUNC:
116                 foo->cleanctx = OSSL_get_OP_foo_cleanctx(fns);
117                 break;
118             case OSSL_OP_FOO_FREECTX_FUNC:
119                 foo->freectx = OSSL_get_OP_foo_freectx(fns);
120                 break;
121             }
122         }
123         foo->nid = foo_type;
124         foo->prov = prov;
125         if (prov)
126             ossl_provider_upref(prov);
127
128         return foo;
129     }
130
131     EVP_FOO_meth_free(EVP_FOO *foo)
132     {
133         if (foo != NULL) {
134             OSSL_PROVIDER *prov = foo->prov;
135
136             OPENSSL_free(foo);
137             ossl_provider_free(prov);
138         }
139     }
140
141     static void *foo_from_dispatch(int nid, const OSSL_DISPATCH *fns,
142                                    OSSL_PROVIDER *prov)
143     {
144         return EVP_FOO_meth_from_dispatch(nid, fns, prov);
145     }
146
147     static int foo_upref(void *vfoo)
148     {
149         EVP_FOO *foo = vfoo;
150         int ref = 0;
151
152         CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
153         return 1;
154     }
155
156     static void foo_free(void *vfoo)
157     {
158         EVP_FOO_meth_free(vfoo);
159     }
160
161     EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx,
162                            const char *name,
163                            const char *properties)
164     {
165         return evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
166                                  foo_from_dispatch, foo_upref, foo_free);
167     }
168
169 And finally, the library functions:
170
171     /* typedef struct evp_foo_st EVP_FOO_CTX */
172     struct evp_foo_ctx_st {
173         const EVP_FOO *foo;
174         void *provctx;          /* corresponding provider context */
175     };
176
177     int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
178     {
179         if (c == NULL)
180             return 1;
181         if (c->foo != NULL && c->foo->cleanctx != NULL)
182             c->foo->cleanctx(c->provctx);
183         return 1;
184     }
185
186     EVP_FOO_CTX *EVP_FOO_CTX_new(void)
187     {
188         return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
189     }
190
191     void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
192     {
193         EVP_FOO_CTX_reset(c);
194         c->foo->freectx(c->provctx);
195         OPENSSL_free(c);
196     }
197
198     int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
199     {
200         int ok = 1;
201
202         c->foo = foo;
203         if (c->provctx == NULL)
204             c->provctx = c->foo->newctx();
205
206         ok = c->foo->init(c->provctx);
207
208         return ok;
209     }
210
211     int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
212                        const unsigned char *in, size_t inl)
213     {
214         int ok = 1;
215
216         ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
217         return ok;
218     }
219
220 =head1 SEE ALSO
221
222 L<ossl_method_construct>
223
224 =head1 HISTORY
225
226 The functions described here were all added in OpenSSL 3.0.
227
228 =head1 COPYRIGHT
229
230 Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
231
232 Licensed under the Apache License 2.0 (the "License").  You may not use
233 this file except in compliance with the License.  You can obtain a copy
234 in the file LICENSE in the source distribution or at
235 L<https://www.openssl.org/source/license.html>.
236
237 =cut