| =pod |
| |
| =head1 NAME |
| |
| evp_generic_fetch - generic algorithm fetcher and method creator for EVP |
| |
| =head1 SYNOPSIS |
| |
| /* Only for EVP source */ |
| #include "evp_locl.h" |
| |
| void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id, |
| const char *algorithm, const char *properties, |
| void *(*new_method)(int nid, const OSSL_DISPATCH *fns, |
| OSSL_PROVIDER *prov), |
| int (*upref_method)(void *), |
| void (*free_method)(void *)); |
| |
| =head1 DESCRIPTION |
| |
| evp_generic_fetch() calls ossl_method_construct() with the given |
| C<libctx>, C<operation_id>, C<algorithm>, and C<properties> and uses |
| it to create an EVP method with the help of the functions |
| C<new_method>, C<upref_method>, and C<free_method>. |
| |
| The three functions are supposed to: |
| |
| =over 4 |
| |
| =item new_method() |
| |
| creates an internal method from function pointers found in the |
| dispatch table C<fns>. |
| |
| =item upref_method() |
| |
| increments the reference counter for the given method, if there is |
| one. |
| |
| =item free_method() |
| |
| frees the given method. |
| |
| =back |
| |
| =head1 RETURN VALUES |
| |
| evp_generic_fetch() returns a method on success, or B<NULL> on error. |
| |
| =head1 EXAMPLES |
| |
| This is a short example of the fictitious EVP API and operation called |
| C<EVP_FOO>. |
| |
| To begin with, let's assume something like this in |
| C<include/openssl/core_numbers.h>: |
| |
| #define OSSL_OP_FOO 100 |
| |
| #define OSSL_OP_FOO_NEWCTX_FUNC 2001 |
| #define OSSL_OP_FOO_INIT 2002 |
| #define OSSL_OP_FOO_OPERATE 2003 |
| #define OSSL_OP_FOO_CLEANCTX_FUNC 2004 |
| #define OSSL_OP_FOO_FREECTX_FUNC 2005 |
| OSSL_CORE_MAKE_FUNC(void *,OP_foo_newctx,(void)) |
| OSSL_CORE_MAKE_FUNC(int,OP_foo_init,(void *vctx)) |
| OSSL_CORE_MAKE_FUNC(int,OP_foo_operate,(void *vctx, |
| unsigned char *out, size_t *out_l, |
| unsigned char *in, size_t in_l)) |
| OSSL_CORE_MAKE_FUNC(void,OP_foo_cleanctx,(void *vctx)) |
| OSSL_CORE_MAKE_FUNC(void,OP_foo_freectx,(void *vctx)) |
| |
| And here's the implementation of the FOO method fetcher: |
| |
| /* typedef struct evp_foo_st EVP_FOO */ |
| struct evp_foo_st { |
| OSSL_PROVIDER *prov; |
| int nid; |
| CRYPTO_REF_COUNT refcnt; |
| OSSL_OP_foo_newctx_fn *newctx; |
| OSSL_OP_foo_init_fn *init; |
| OSSL_OP_foo_operate_fn *operate; |
| OSSL_OP_foo_cleanctx_fn *cleanctx; |
| OSSL_OP_foo_freectx_fn *freectx; |
| }; |
| |
| /* |
| * In this example, we have a public method creator and destructor. |
| * It's not absolutely necessary, but is in the spirit of OpenSSL. |
| */ |
| EVP_FOO *EVP_FOO_meth_from_dispatch(int foo_type, const OSSL_DISPATCH *fns, |
| OSSL_PROVIDER *prov) |
| { |
| EVP_FOO *foo = NULL; |
| |
| if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL) |
| return NULL; |
| |
| for (; fns->function_id != 0; fns++) { |
| switch (fns->function_id) { |
| case OSSL_OP_FOO_NEWCTX_FUNC: |
| foo->newctx = OSSL_get_OP_foo_newctx(fns); |
| break; |
| case OSSL_OP_FOO_INIT: |
| foo->init = OSSL_get_OP_foo_init(fns); |
| break; |
| case OSSL_OP_FOO_OPERATE: |
| foo->operate = OSSL_get_OP_foo_operate(fns); |
| break; |
| case OSSL_OP_FOO_CLEANCTX_FUNC: |
| foo->cleanctx = OSSL_get_OP_foo_cleanctx(fns); |
| break; |
| case OSSL_OP_FOO_FREECTX_FUNC: |
| foo->freectx = OSSL_get_OP_foo_freectx(fns); |
| break; |
| } |
| } |
| foo->nid = foo_type; |
| foo->prov = prov; |
| if (prov) |
| ossl_provider_upref(prov); |
| |
| return foo; |
| } |
| |
| EVP_FOO_meth_free(EVP_FOO *foo) |
| { |
| if (foo != NULL) { |
| OSSL_PROVIDER *prov = foo->prov; |
| |
| OPENSSL_free(foo); |
| ossl_provider_free(prov); |
| } |
| } |
| |
| static void *foo_from_dispatch(int nid, const OSSL_DISPATCH *fns, |
| OSSL_PROVIDER *prov) |
| { |
| return EVP_FOO_meth_from_dispatch(nid, fns, prov); |
| } |
| |
| static int foo_upref(void *vfoo) |
| { |
| EVP_FOO *foo = vfoo; |
| int ref = 0; |
| |
| CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock); |
| return 1; |
| } |
| |
| static void foo_free(void *vfoo) |
| { |
| EVP_FOO_meth_free(vfoo); |
| } |
| |
| EVP_FOO *EVP_FOO_fetch(OPENSSL_CTX *ctx, |
| const char *algorithm, |
| const char *properties) |
| { |
| return evp_generic_fetch(ctx, OSSL_OP_FOO, algorithm, properties, |
| foo_from_dispatch, foo_upref, foo_free); |
| } |
| |
| And finally, the library functions: |
| |
| /* typedef struct evp_foo_st EVP_FOO_CTX */ |
| struct evp_foo_ctx_st { |
| const EVP_FOO *foo; |
| void *provctx; /* corresponding provider context */ |
| }; |
| |
| int EVP_FOO_CTX_reset(EVP_FOO_CTX *c) |
| { |
| if (c == NULL) |
| return 1; |
| if (c->foo != NULL && c->foo->cleanctx != NULL) |
| c->foo->cleanctx(c->provctx); |
| return 1; |
| } |
| |
| EVP_FOO_CTX *EVP_FOO_CTX_new(void) |
| { |
| return OPENSSL_zalloc(sizeof(EVP_FOO_CTX)); |
| } |
| |
| void EVP_FOO_CTX_free(EVP_FOO_CTX *c) |
| { |
| EVP_FOO_CTX_reset(c); |
| c->foo->freectx(c->provctx); |
| OPENSSL_free(c); |
| } |
| |
| int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo) |
| { |
| int ok = 1; |
| |
| c->foo = foo; |
| if (c->provctx == NULL) |
| c->provctx = c->foo->newctx(); |
| |
| ok = c->foo->init(c->provctx); |
| |
| return ok; |
| } |
| |
| int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl, |
| const unsigned char *in, size_t inl) |
| { |
| int ok = 1; |
| |
| ok = c->foo->update(c->provctx, out, inl, &outl, in, inl); |
| return ok; |
| } |
| |
| =head1 SEE ALSO |
| |
| L<ossl_method_construct> |
| |
| =head1 HISTORY |
| |
| The functions described here were all added in OpenSSL 3.0. |
| |
| =head1 COPYRIGHT |
| |
| Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. |
| |
| Licensed under the Apache License 2.0 (the "License"). You may not use |
| this file except in compliance with the License. You can obtain a copy |
| in the file LICENSE in the source distribution or at |
| L<https://www.openssl.org/source/license.html>. |
| |
| =cut |