1*b077aed3SPierre Pronchery=pod 2*b077aed3SPierre Pronchery 3*b077aed3SPierre Pronchery=head1 NAME 4*b077aed3SPierre Pronchery 5*b077aed3SPierre Proncheryevp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov 6*b077aed3SPierre Pronchery- generic algorithm fetchers and method creators for EVP 7*b077aed3SPierre Pronchery 8*b077aed3SPierre Pronchery=head1 SYNOPSIS 9*b077aed3SPierre Pronchery 10*b077aed3SPierre Pronchery /* Only for EVP source */ 11*b077aed3SPierre Pronchery #include "evp_local.h" 12*b077aed3SPierre Pronchery 13*b077aed3SPierre Pronchery void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id, 14*b077aed3SPierre Pronchery const char *name, const char *properties, 15*b077aed3SPierre Pronchery void *(*new_method)(int name_id, 16*b077aed3SPierre Pronchery const OSSL_DISPATCH *fns, 17*b077aed3SPierre Pronchery OSSL_PROVIDER *prov, 18*b077aed3SPierre Pronchery void *method_data), 19*b077aed3SPierre Pronchery void *method_data, 20*b077aed3SPierre Pronchery int (*up_ref_method)(void *), 21*b077aed3SPierre Pronchery void (*free_method)(void *)); 22*b077aed3SPierre Pronchery 23*b077aed3SPierre Pronchery void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id, 24*b077aed3SPierre Pronchery int name_id, const char *properties, 25*b077aed3SPierre Pronchery void *(*new_method)(int name_id, 26*b077aed3SPierre Pronchery const OSSL_DISPATCH *fns, 27*b077aed3SPierre Pronchery OSSL_PROVIDER *prov, 28*b077aed3SPierre Pronchery void *method_data), 29*b077aed3SPierre Pronchery void *method_data, 30*b077aed3SPierre Pronchery int (*up_ref_method)(void *), 31*b077aed3SPierre Pronchery void (*free_method)(void *)); 32*b077aed3SPierre Pronchery void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, 33*b077aed3SPierre Pronchery int name_id, const char *properties, 34*b077aed3SPierre Pronchery void *(*new_method)(int name_id, 35*b077aed3SPierre Pronchery const OSSL_DISPATCH *fns, 36*b077aed3SPierre Pronchery OSSL_PROVIDER *prov, 37*b077aed3SPierre Pronchery void *method_data), 38*b077aed3SPierre Pronchery void *method_data, 39*b077aed3SPierre Pronchery int (*up_ref_method)(void *), 40*b077aed3SPierre Pronchery void (*free_method)(void *)); 41*b077aed3SPierre Pronchery 42*b077aed3SPierre Pronchery=head1 DESCRIPTION 43*b077aed3SPierre Pronchery 44*b077aed3SPierre Proncheryevp_generic_fetch() calls ossl_method_construct() with the given 45*b077aed3SPierre ProncheryI<libctx>, I<operation_id>, I<name>, and I<properties> and uses 46*b077aed3SPierre Proncheryit to create an EVP method with the help of the functions 47*b077aed3SPierre ProncheryI<new_method>, I<up_ref_method>, and I<free_method>. 48*b077aed3SPierre Pronchery 49*b077aed3SPierre Proncheryevp_generic_fetch_by_number() does the same thing as evp_generic_fetch(), 50*b077aed3SPierre Proncherybut takes a numeric I<name_id> instead of a name. 51*b077aed3SPierre ProncheryI<name_id> must always be nonzero; as a matter of fact, it being zero 52*b077aed3SPierre Proncheryis considered a programming error. 53*b077aed3SPierre ProncheryThis is meant to be used when one method needs to fetch an associated 54*b077aed3SPierre Proncherymethod, and is typically called from inside the given function 55*b077aed3SPierre ProncheryI<new_method>. 56*b077aed3SPierre Pronchery 57*b077aed3SPierre Proncheryevp_generic_fetch_from_prov() does the same thing as evp_generic_fetch(), 58*b077aed3SPierre Proncherybut limits the search of methods to the provider given with I<prov>. 59*b077aed3SPierre ProncheryThis is meant to be used when one method needs to fetch an associated 60*b077aed3SPierre Proncherymethod in the same provider. 61*b077aed3SPierre Pronchery 62*b077aed3SPierre ProncheryThe three functions I<new_method>, I<up_ref_method>, and 63*b077aed3SPierre ProncheryI<free_method> are supposed to: 64*b077aed3SPierre Pronchery 65*b077aed3SPierre Pronchery=over 4 66*b077aed3SPierre Pronchery 67*b077aed3SPierre Pronchery=item new_method() 68*b077aed3SPierre Pronchery 69*b077aed3SPierre Proncherycreates an internal method from function pointers found in the 70*b077aed3SPierre Proncherydispatch table I<fns>, with name identity I<name_id>. 71*b077aed3SPierre ProncheryThe provider I<prov> and I<method_data> are also passed to be used as 72*b077aed3SPierre Proncherynew_method() sees fit. 73*b077aed3SPierre Pronchery 74*b077aed3SPierre Pronchery=item up_ref_method() 75*b077aed3SPierre Pronchery 76*b077aed3SPierre Proncheryincrements the reference counter for the given method, if there is 77*b077aed3SPierre Proncheryone. 78*b077aed3SPierre Pronchery 79*b077aed3SPierre Pronchery=item free_method() 80*b077aed3SPierre Pronchery 81*b077aed3SPierre Proncheryfrees the given method. 82*b077aed3SPierre Pronchery 83*b077aed3SPierre Pronchery=back 84*b077aed3SPierre Pronchery 85*b077aed3SPierre Pronchery=head1 RETURN VALUES 86*b077aed3SPierre Pronchery 87*b077aed3SPierre Proncheryevp_generic_fetch() returns a method on success, or NULL on error. 88*b077aed3SPierre Pronchery 89*b077aed3SPierre Pronchery=head1 EXAMPLES 90*b077aed3SPierre Pronchery 91*b077aed3SPierre ProncheryThis is a short example of the fictitious EVP API and operation called 92*b077aed3SPierre ProncheryB<EVP_FOO>. 93*b077aed3SPierre Pronchery 94*b077aed3SPierre ProncheryTo begin with, let's assume something like this in 95*b077aed3SPierre ProncheryF<include/openssl/core_dispatch.h>: 96*b077aed3SPierre Pronchery 97*b077aed3SPierre Pronchery #define OSSL_OP_FOO 100 98*b077aed3SPierre Pronchery 99*b077aed3SPierre Pronchery #define OSSL_FUNC_FOO_NEWCTX_FUNC 2001 100*b077aed3SPierre Pronchery #define OSSL_FUNC_FOO_INIT 2002 101*b077aed3SPierre Pronchery #define OSSL_FUNC_FOO_OPERATE 2003 102*b077aed3SPierre Pronchery #define OSSL_FUNC_FOO_CLEANCTX_FUNC 2004 103*b077aed3SPierre Pronchery #define OSSL_FUNC_FOO_FREECTX_FUNC 2005 104*b077aed3SPierre Pronchery 105*b077aed3SPierre Pronchery OSSL_CORE_MAKE_FUNC(void *, foo_newctx, (void)) 106*b077aed3SPierre Pronchery OSSL_CORE_MAKE_FUNC(int, foo_init, (void *vctx)) 107*b077aed3SPierre Pronchery OSSL_CORE_MAKE_FUNC(int, foo_operate, (void *vctx, 108*b077aed3SPierre Pronchery unsigned char *out, size_t *out_l, 109*b077aed3SPierre Pronchery unsigned char *in, size_t in_l)) 110*b077aed3SPierre Pronchery OSSL_CORE_MAKE_FUNC(void, foo_cleanctx, (void *vctx)) 111*b077aed3SPierre Pronchery OSSL_CORE_MAKE_FUNC(void, foo_freectx, (void *vctx)) 112*b077aed3SPierre Pronchery 113*b077aed3SPierre ProncheryAnd here's the implementation of the FOO method fetcher: 114*b077aed3SPierre Pronchery 115*b077aed3SPierre Pronchery /* typedef struct evp_foo_st EVP_FOO */ 116*b077aed3SPierre Pronchery struct evp_foo_st { 117*b077aed3SPierre Pronchery OSSL_PROVIDER *prov; 118*b077aed3SPierre Pronchery int name_id; 119*b077aed3SPierre Pronchery CRYPTO_REF_COUNT refcnt; 120*b077aed3SPierre Pronchery OSSL_FUNC_foo_newctx_fn *newctx; 121*b077aed3SPierre Pronchery OSSL_FUNC_foo_init_fn *init; 122*b077aed3SPierre Pronchery OSSL_FUNC_foo_operate_fn *operate; 123*b077aed3SPierre Pronchery OSSL_FUNC_foo_cleanctx_fn *cleanctx; 124*b077aed3SPierre Pronchery OSSL_FUNC_foo_freectx_fn *freectx; 125*b077aed3SPierre Pronchery }; 126*b077aed3SPierre Pronchery 127*b077aed3SPierre Pronchery /* 128*b077aed3SPierre Pronchery * In this example, we have a public method creator and destructor. 129*b077aed3SPierre Pronchery * It's not absolutely necessary, but is in the spirit of OpenSSL. 130*b077aed3SPierre Pronchery */ 131*b077aed3SPierre Pronchery EVP_FOO *EVP_FOO_meth_from_algorithm(int name_id, 132*b077aed3SPierre Pronchery const OSSL_DISPATCH *fns, 133*b077aed3SPierre Pronchery OSSL_PROVIDER *prov, 134*b077aed3SPierre Pronchery void *data) 135*b077aed3SPierre Pronchery { 136*b077aed3SPierre Pronchery EVP_FOO *foo = NULL; 137*b077aed3SPierre Pronchery 138*b077aed3SPierre Pronchery if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL) 139*b077aed3SPierre Pronchery return NULL; 140*b077aed3SPierre Pronchery 141*b077aed3SPierre Pronchery foo->name_id = name_id; 142*b077aed3SPierre Pronchery 143*b077aed3SPierre Pronchery for (; fns->function_id != 0; fns++) { 144*b077aed3SPierre Pronchery switch (fns->function_id) { 145*b077aed3SPierre Pronchery case OSSL_FUNC_FOO_NEWCTX: 146*b077aed3SPierre Pronchery foo->newctx = OSSL_FUNC_foo_newctx(fns); 147*b077aed3SPierre Pronchery break; 148*b077aed3SPierre Pronchery case OSSL_FUNC_FOO_INIT: 149*b077aed3SPierre Pronchery foo->init = OSSL_FUNC_foo_init(fns); 150*b077aed3SPierre Pronchery break; 151*b077aed3SPierre Pronchery case OSSL_FUNC_FOO_OPERATE: 152*b077aed3SPierre Pronchery foo->operate = OSSL_FUNC_foo_operate(fns); 153*b077aed3SPierre Pronchery break; 154*b077aed3SPierre Pronchery case OSSL_FUNC_FOO_CLEANCTX: 155*b077aed3SPierre Pronchery foo->cleanctx = OSSL_FUNC_foo_cleanctx(fns); 156*b077aed3SPierre Pronchery break; 157*b077aed3SPierre Pronchery case OSSL_FUNC_FOO_FREECTX: 158*b077aed3SPierre Pronchery foo->freectx = OSSL_FUNC_foo_freectx(fns); 159*b077aed3SPierre Pronchery break; 160*b077aed3SPierre Pronchery } 161*b077aed3SPierre Pronchery } 162*b077aed3SPierre Pronchery foo->prov = prov; 163*b077aed3SPierre Pronchery if (prov) 164*b077aed3SPierre Pronchery ossl_provider_up_ref(prov); 165*b077aed3SPierre Pronchery 166*b077aed3SPierre Pronchery return foo; 167*b077aed3SPierre Pronchery } 168*b077aed3SPierre Pronchery 169*b077aed3SPierre Pronchery EVP_FOO_meth_free(EVP_FOO *foo) 170*b077aed3SPierre Pronchery { 171*b077aed3SPierre Pronchery if (foo != NULL) { 172*b077aed3SPierre Pronchery OSSL_PROVIDER *prov = foo->prov; 173*b077aed3SPierre Pronchery 174*b077aed3SPierre Pronchery OPENSSL_free(foo); 175*b077aed3SPierre Pronchery ossl_provider_free(prov); 176*b077aed3SPierre Pronchery } 177*b077aed3SPierre Pronchery } 178*b077aed3SPierre Pronchery 179*b077aed3SPierre Pronchery static void *foo_from_algorithm(const OSSL_DISPATCH *fns, 180*b077aed3SPierre Pronchery OSSL_PROVIDER *prov) 181*b077aed3SPierre Pronchery { 182*b077aed3SPierre Pronchery return EVP_FOO_meth_from_algorithm(fns, prov); 183*b077aed3SPierre Pronchery } 184*b077aed3SPierre Pronchery 185*b077aed3SPierre Pronchery static int foo_up_ref(void *vfoo) 186*b077aed3SPierre Pronchery { 187*b077aed3SPierre Pronchery EVP_FOO *foo = vfoo; 188*b077aed3SPierre Pronchery int ref = 0; 189*b077aed3SPierre Pronchery 190*b077aed3SPierre Pronchery CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock); 191*b077aed3SPierre Pronchery return 1; 192*b077aed3SPierre Pronchery } 193*b077aed3SPierre Pronchery 194*b077aed3SPierre Pronchery static void foo_free(void *vfoo) 195*b077aed3SPierre Pronchery { 196*b077aed3SPierre Pronchery EVP_FOO_meth_free(vfoo); 197*b077aed3SPierre Pronchery } 198*b077aed3SPierre Pronchery 199*b077aed3SPierre Pronchery EVP_FOO *EVP_FOO_fetch(OSSL_LIB_CTX *ctx, 200*b077aed3SPierre Pronchery const char *name, 201*b077aed3SPierre Pronchery const char *properties) 202*b077aed3SPierre Pronchery { 203*b077aed3SPierre Pronchery EVP_FOO *foo = 204*b077aed3SPierre Pronchery evp_generic_fetch(ctx, OSSL_OP_FOO, name, properties, 205*b077aed3SPierre Pronchery foo_from_algorithm, foo_up_ref, foo_free); 206*b077aed3SPierre Pronchery 207*b077aed3SPierre Pronchery /* 208*b077aed3SPierre Pronchery * If this method exists in legacy form, with a constant NID for the 209*b077aed3SPierre Pronchery * given |name|, this is the spot to find that NID and set it in 210*b077aed3SPierre Pronchery * the newly constructed EVP_FOO instance. 211*b077aed3SPierre Pronchery */ 212*b077aed3SPierre Pronchery 213*b077aed3SPierre Pronchery return foo; 214*b077aed3SPierre Pronchery 215*b077aed3SPierre Pronchery } 216*b077aed3SPierre Pronchery 217*b077aed3SPierre ProncheryAnd finally, the library functions: 218*b077aed3SPierre Pronchery 219*b077aed3SPierre Pronchery /* typedef struct evp_foo_st EVP_FOO_CTX */ 220*b077aed3SPierre Pronchery struct evp_foo_ctx_st { 221*b077aed3SPierre Pronchery const EVP_FOO *foo; 222*b077aed3SPierre Pronchery void *provctx; /* corresponding provider context */ 223*b077aed3SPierre Pronchery }; 224*b077aed3SPierre Pronchery 225*b077aed3SPierre Pronchery int EVP_FOO_CTX_reset(EVP_FOO_CTX *c) 226*b077aed3SPierre Pronchery { 227*b077aed3SPierre Pronchery if (c == NULL) 228*b077aed3SPierre Pronchery return 1; 229*b077aed3SPierre Pronchery if (c->foo != NULL && c->foo->cleanctx != NULL) 230*b077aed3SPierre Pronchery c->foo->cleanctx(c->provctx); 231*b077aed3SPierre Pronchery return 1; 232*b077aed3SPierre Pronchery } 233*b077aed3SPierre Pronchery 234*b077aed3SPierre Pronchery EVP_FOO_CTX *EVP_FOO_CTX_new(void) 235*b077aed3SPierre Pronchery { 236*b077aed3SPierre Pronchery return OPENSSL_zalloc(sizeof(EVP_FOO_CTX)); 237*b077aed3SPierre Pronchery } 238*b077aed3SPierre Pronchery 239*b077aed3SPierre Pronchery void EVP_FOO_CTX_free(EVP_FOO_CTX *c) 240*b077aed3SPierre Pronchery { 241*b077aed3SPierre Pronchery EVP_FOO_CTX_reset(c); 242*b077aed3SPierre Pronchery c->foo->freectx(c->provctx); 243*b077aed3SPierre Pronchery OPENSSL_free(c); 244*b077aed3SPierre Pronchery } 245*b077aed3SPierre Pronchery 246*b077aed3SPierre Pronchery int EVP_FooInit(EVP_FOO_CTX *c, const EVP_FOO *foo) 247*b077aed3SPierre Pronchery { 248*b077aed3SPierre Pronchery int ok = 1; 249*b077aed3SPierre Pronchery 250*b077aed3SPierre Pronchery c->foo = foo; 251*b077aed3SPierre Pronchery if (c->provctx == NULL) 252*b077aed3SPierre Pronchery c->provctx = c->foo->newctx(); 253*b077aed3SPierre Pronchery 254*b077aed3SPierre Pronchery ok = c->foo->init(c->provctx); 255*b077aed3SPierre Pronchery 256*b077aed3SPierre Pronchery return ok; 257*b077aed3SPierre Pronchery } 258*b077aed3SPierre Pronchery 259*b077aed3SPierre Pronchery int EVP_FooOperate(EVP_FOO_CTX *c, unsigned char *out, size_t *outl, 260*b077aed3SPierre Pronchery const unsigned char *in, size_t inl) 261*b077aed3SPierre Pronchery { 262*b077aed3SPierre Pronchery int ok = 1; 263*b077aed3SPierre Pronchery 264*b077aed3SPierre Pronchery ok = c->foo->update(c->provctx, out, inl, &outl, in, inl); 265*b077aed3SPierre Pronchery return ok; 266*b077aed3SPierre Pronchery } 267*b077aed3SPierre Pronchery 268*b077aed3SPierre Pronchery=head1 SEE ALSO 269*b077aed3SPierre Pronchery 270*b077aed3SPierre ProncheryL<ossl_method_construct(3)> 271*b077aed3SPierre Pronchery 272*b077aed3SPierre Pronchery=head1 HISTORY 273*b077aed3SPierre Pronchery 274*b077aed3SPierre ProncheryThe functions described here were all added in OpenSSL 3.0. 275*b077aed3SPierre Pronchery 276*b077aed3SPierre Pronchery=head1 COPYRIGHT 277*b077aed3SPierre Pronchery 278*b077aed3SPierre ProncheryCopyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 279*b077aed3SPierre Pronchery 280*b077aed3SPierre ProncheryLicensed under the Apache License 2.0 (the "License"). You may not use 281*b077aed3SPierre Proncherythis file except in compliance with the License. You can obtain a copy 282*b077aed3SPierre Proncheryin the file LICENSE in the source distribution or at 283*b077aed3SPierre ProncheryL<https://www.openssl.org/source/license.html>. 284*b077aed3SPierre Pronchery 285*b077aed3SPierre Pronchery=cut 286