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