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