ossl_provider_upref to ossl_provider_up_ref
[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 OSSL_DISPATCH *fns,
15                                              OSSL_PROVIDER *prov),
16                          int (*up_ref_method)(void *),
17                          void (*free_method)(void *));
18
19 =head1 DESCRIPTION
20
21 evp_generic_fetch() calls ossl_method_construct() with the given
22 C<libctx>, C<operation_id>, C<name>, and C<properties> and uses
23 it to create an EVP method with the help of the functions
24 C<new_method>, C<up_ref_method>, and C<free_method>.
25
26 The three functions are supposed to:
27
28 =over 4
29
30 =item new_method()
31
32 creates an internal method from function pointers found in the
33 dispatch table C<fns>.
34
35 =item up_ref_method()
36
37 increments the reference counter for the given method, if there is
38 one.
39
40 =item free_method()
41
42 frees the given method.
43
44 =back
45
46 =head1 RETURN VALUES
47
48 evp_generic_fetch() returns a method on success, or B<NULL> on error.
49
50 =head1 EXAMPLES
51
52 This is a short example of the fictitious EVP API and operation called
53 C<EVP_FOO>.
54
55 To begin with, let's assume something like this in
56 C<include/openssl/core_numbers.h>:
57
58     #define OSSL_OP_FOO                         100
59
60     #define OSSL_OP_FOO_NEWCTX_FUNC            2001
61     #define OSSL_OP_FOO_INIT                   2002
62     #define OSSL_OP_FOO_OPERATE                2003
63     #define OSSL_OP_FOO_CLEANCTX_FUNC          2004
64     #define OSSL_OP_FOO_FREECTX_FUNC           2005
65     OSSL_CORE_MAKE_FUNC(void *,OP_foo_newctx,(void))
66     OSSL_CORE_MAKE_FUNC(int,OP_foo_init,(void *vctx))
67     OSSL_CORE_MAKE_FUNC(int,OP_foo_operate,(void *vctx,
68                                             unsigned char *out, size_t *out_l,
69                                             unsigned char *in, size_t in_l))
70     OSSL_CORE_MAKE_FUNC(void,OP_foo_cleanctx,(void *vctx))
71     OSSL_CORE_MAKE_FUNC(void,OP_foo_freectx,(void *vctx))
72
73 And here's the implementation of the FOO method fetcher:
74
75     /* typedef struct evp_foo_st EVP_FOO */
76     struct evp_foo_st {
77         OSSL_PROVIDER *prov;
78         CRYPTO_REF_COUNT refcnt;
79         OSSL_OP_foo_newctx_fn *newctx;
80         OSSL_OP_foo_init_fn *init;
81         OSSL_OP_foo_operate_fn *operate;
82         OSSL_OP_foo_cleanctx_fn *cleanctx;
83         OSSL_OP_foo_freectx_fn *freectx;
84     };
85
86     /*
87      * In this example, we have a public method creator and destructor.
88      * It's not absolutely necessary, but is in the spirit of OpenSSL.
89      */
90     EVP_FOO *EVP_FOO_meth_from_dispatch(const OSSL_DISPATCH *fns,
91                                         OSSL_PROVIDER *prov)
92     {
93         EVP_FOO *foo = NULL;
94
95         if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
96             return NULL;
97
98         for (; fns->function_id != 0; fns++) {
99             switch (fns->function_id) {
100             case OSSL_OP_FOO_NEWCTX_FUNC:
101                 foo->newctx = OSSL_get_OP_foo_newctx(fns);
102                 break;
103             case OSSL_OP_FOO_INIT:
104                 foo->init = OSSL_get_OP_foo_init(fns);
105                 break;
106             case OSSL_OP_FOO_OPERATE:
107                 foo->operate = OSSL_get_OP_foo_operate(fns);
108                 break;
109             case OSSL_OP_FOO_CLEANCTX_FUNC:
110                 foo->cleanctx = OSSL_get_OP_foo_cleanctx(fns);
111                 break;
112             case OSSL_OP_FOO_FREECTX_FUNC:
113                 foo->freectx = OSSL_get_OP_foo_freectx(fns);
114                 break;
115             }
116         }
117         foo->prov = prov;
118         if (prov)
119             ossl_provider_up_ref(prov);
120
121         return foo;
122     }
123
124     EVP_FOO_meth_free(EVP_FOO *foo)
125     {
126         if (foo != NULL) {
127             OSSL_PROVIDER *prov = foo->prov;
128
129             OPENSSL_free(foo);
130             ossl_provider_free(prov);
131         }
132     }
133
134     static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
135                                    OSSL_PROVIDER *prov)
136     {
137         return EVP_FOO_meth_from_dispatch(fns, prov);
138     }
139
140     static int foo_up_ref(void *vfoo)
141     {
142         EVP_FOO *foo = vfoo;
143         int ref = 0;
144
145         CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
146         return 1;
147     }
148
149     static void foo_free(void *vfoo)
150     {
151         EVP_FOO_meth_free(vfoo);
152     }
153
154     EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx,
155                            const char *name,
156                            const char *properties)
157     {
158         EVP_FOO *foo =
159             evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
160                               foo_from_dispatch, foo_up_ref, foo_free);
161
162         /*
163          * If this method exists in legacy form, with a constant NID for the
164          * given |name|, this is the spot to find that NID and set it in
165          * the newly constructed EVP_FOO instance.
166          */
167
168         return foo;
169
170     }
171
172 And finally, the library functions:
173
174     /* typedef struct evp_foo_st EVP_FOO_CTX */
175     struct evp_foo_ctx_st {
176         const EVP_FOO *foo;
177         void *provctx;          /* corresponding provider context */
178     };
179
180     int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
181     {
182         if (c == NULL)
183             return 1;
184         if (c->foo != NULL && c->foo->cleanctx != NULL)
185             c->foo->cleanctx(c->provctx);
186         return 1;
187     }
188
189     EVP_FOO_CTX *EVP_FOO_CTX_new(void)
190     {
191         return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
192     }
193
194     void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
195     {
196         EVP_FOO_CTX_reset(c);
197         c->foo->freectx(c->provctx);
198         OPENSSL_free(c);
199     }
200
201     int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
202     {
203         int ok = 1;
204
205         c->foo = foo;
206         if (c->provctx == NULL)
207             c->provctx = c->foo->newctx();
208
209         ok = c->foo->init(c->provctx);
210
211         return ok;
212     }
213
214     int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
215                        const unsigned char *in, size_t inl)
216     {
217         int ok = 1;
218
219         ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
220         return ok;
221     }
222
223 =head1 SEE ALSO
224
225 L<ossl_method_construct>
226
227 =head1 HISTORY
228
229 The functions described here were all added in OpenSSL 3.0.
230
231 =head1 COPYRIGHT
232
233 Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
234
235 Licensed under the Apache License 2.0 (the "License").  You may not use
236 this file except in compliance with the License.  You can obtain a copy
237 in the file LICENSE in the source distribution or at
238 L<https://www.openssl.org/source/license.html>.
239
240 =cut