5 evp_generic_fetch, evp_generic_fetch_by_number
6 - generic algorithm fetchers and method creators for EVP
10 /* Only for EVP source */
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,
20 int (*up_ref_method)(void *),
21 void (*free_method)(void *));
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,
30 int (*up_ref_method)(void *),
31 void (*free_method)(void *));
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>.
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 non-zero; 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
48 The three functions I<new_method>, I<up_ref_method>, and
49 I<free_method> are supposed to:
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.
62 increments the reference counter for the given method, if there is
67 frees the given method.
73 evp_generic_fetch() returns a method on success, or NULL on error.
77 This is a short example of the fictitious EVP API and operation called
80 To begin with, let's assume something like this in
81 F<include/openssl/core_numbers.h>:
83 #define OSSL_OP_FOO 100
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))
98 And here's the implementation of the FOO method fetcher:
100 /* typedef struct evp_foo_st EVP_FOO */
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;
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.
116 EVP_FOO *EVP_FOO_meth_from_dispatch(int name_id,
117 const OSSL_DISPATCH *fns,
123 if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
126 foo->name_id = name_id;
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);
133 case OSSL_OP_FOO_INIT:
134 foo->init = OSSL_get_OP_foo_init(fns);
136 case OSSL_OP_FOO_OPERATE:
137 foo->operate = OSSL_get_OP_foo_operate(fns);
139 case OSSL_OP_FOO_CLEANCTX_FUNC:
140 foo->cleanctx = OSSL_get_OP_foo_cleanctx(fns);
142 case OSSL_OP_FOO_FREECTX_FUNC:
143 foo->freectx = OSSL_get_OP_foo_freectx(fns);
149 ossl_provider_up_ref(prov);
154 EVP_FOO_meth_free(EVP_FOO *foo)
157 OSSL_PROVIDER *prov = foo->prov;
160 ossl_provider_free(prov);
164 static void *foo_from_dispatch(const OSSL_DISPATCH *fns,
167 return EVP_FOO_meth_from_dispatch(fns, prov);
170 static int foo_up_ref(void *vfoo)
175 CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
179 static void foo_free(void *vfoo)
181 EVP_FOO_meth_free(vfoo);
184 EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx,
186 const char *properties)
189 evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
190 foo_from_dispatch, foo_up_ref, foo_free);
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.
202 And finally, the library functions:
204 /* typedef struct evp_foo_st EVP_FOO_CTX */
205 struct evp_foo_ctx_st {
207 void *provctx; /* corresponding provider context */
210 int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
214 if (c->foo != NULL && c->foo->cleanctx != NULL)
215 c->foo->cleanctx(c->provctx);
219 EVP_FOO_CTX *EVP_FOO_CTX_new(void)
221 return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
224 void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
226 EVP_FOO_CTX_reset(c);
227 c->foo->freectx(c->provctx);
231 int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
236 if (c->provctx == NULL)
237 c->provctx = c->foo->newctx();
239 ok = c->foo->init(c->provctx);
244 int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
245 const unsigned char *in, size_t inl)
249 ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
255 L<ossl_method_construct>
259 The functions described here were all added in OpenSSL 3.0.
263 Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
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>.