5 evp_generic_fetch, evp_generic_fetch_by_number
6 - generic algorithm fetchers and method creators for EVP
10 /* Only for EVP source */
11 #include "evp_local.h"
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,
20 int (*up_ref_method)(void *),
21 void (*free_method)(void *));
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,
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 numeric I<name_id> instead of a name.
42 I<name_id> must always be nonzero; 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_dispatch.h>:
83 #define OSSL_OP_FOO 100
85 #define OSSL_FUNC_FOO_NEWCTX_FUNC 2001
86 #define OSSL_FUNC_FOO_INIT 2002
87 #define OSSL_FUNC_FOO_OPERATE 2003
88 #define OSSL_FUNC_FOO_CLEANCTX_FUNC 2004
89 #define OSSL_FUNC_FOO_FREECTX_FUNC 2005
91 OSSL_CORE_MAKE_FUNC(void *, foo_newctx, (void))
92 OSSL_CORE_MAKE_FUNC(int, foo_init, (void *vctx))
93 OSSL_CORE_MAKE_FUNC(int, foo_operate, (void *vctx,
94 unsigned char *out, size_t *out_l,
95 unsigned char *in, size_t in_l))
96 OSSL_CORE_MAKE_FUNC(void, foo_cleanctx, (void *vctx))
97 OSSL_CORE_MAKE_FUNC(void, foo_freectx, (void *vctx))
99 And here's the implementation of the FOO method fetcher:
101 /* typedef struct evp_foo_st EVP_FOO */
105 CRYPTO_REF_COUNT refcnt;
106 OSSL_FUNC_foo_newctx_fn *newctx;
107 OSSL_FUNC_foo_init_fn *init;
108 OSSL_FUNC_foo_operate_fn *operate;
109 OSSL_FUNC_foo_cleanctx_fn *cleanctx;
110 OSSL_FUNC_foo_freectx_fn *freectx;
114 * In this example, we have a public method creator and destructor.
115 * It's not absolutely necessary, but is in the spirit of OpenSSL.
117 EVP_FOO *EVP_FOO_meth_from_algorithm(int name_id,
118 const OSSL_DISPATCH *fns,
124 if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL)
127 foo->name_id = name_id;
129 for (; fns->function_id != 0; fns++) {
130 switch (fns->function_id) {
131 case OSSL_FUNC_FOO_NEWCTX:
132 foo->newctx = OSSL_FUNC_foo_newctx(fns);
134 case OSSL_FUNC_FOO_INIT:
135 foo->init = OSSL_FUNC_foo_init(fns);
137 case OSSL_FUNC_FOO_OPERATE:
138 foo->operate = OSSL_FUNC_foo_operate(fns);
140 case OSSL_FUNC_FOO_CLEANCTX:
141 foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns);
143 case OSSL_FUNC_FOO_FREECTX:
144 foo->freectx = OSSL_FUNC_foo_freectx(fns);
150 ossl_provider_up_ref(prov);
155 EVP_FOO_meth_free(EVP_FOO *foo)
158 OSSL_PROVIDER *prov = foo->prov;
161 ossl_provider_free(prov);
165 static void *foo_from_algorithm(const OSSL_DISPATCH *fns,
168 return EVP_FOO_meth_from_algorithm(fns, prov);
171 static int foo_up_ref(void *vfoo)
176 CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock);
180 static void foo_free(void *vfoo)
182 EVP_FOO_meth_free(vfoo);
185 EVP_FOO *EVP_FOO_fetch(OSSL_LIB_CTX *ctx,
187 const char *properties)
190 evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties,
191 foo_from_algorithm, foo_up_ref, foo_free);
194 * If this method exists in legacy form, with a constant NID for the
195 * given |name|, this is the spot to find that NID and set it in
196 * the newly constructed EVP_FOO instance.
203 And finally, the library functions:
205 /* typedef struct evp_foo_st EVP_FOO_CTX */
206 struct evp_foo_ctx_st {
208 void *provctx; /* corresponding provider context */
211 int EVP_FOO_CTX_reset(EVP_FOO_CTX *c)
215 if (c->foo != NULL && c->foo->cleanctx != NULL)
216 c->foo->cleanctx(c->provctx);
220 EVP_FOO_CTX *EVP_FOO_CTX_new(void)
222 return OPENSSL_zalloc(sizeof(EVP_FOO_CTX));
225 void EVP_FOO_CTX_free(EVP_FOO_CTX *c)
227 EVP_FOO_CTX_reset(c);
228 c->foo->freectx(c->provctx);
232 int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo)
237 if (c->provctx == NULL)
238 c->provctx = c->foo->newctx();
240 ok = c->foo->init(c->provctx);
245 int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl,
246 const unsigned char *in, size_t inl)
250 ok = c->foo->update(c->provctx, out, inl, &outl, in, inl);
256 L<ossl_method_construct(3)>
260 The functions described here were all added in OpenSSL 3.0.
264 Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
266 Licensed under the Apache License 2.0 (the "License"). You may not use
267 this file except in compliance with the License. You can obtain a copy
268 in the file LICENSE in the source distribution or at
269 L<https://www.openssl.org/source/license.html>.