Latest update
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
=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
|
||||
@@ -49,6 +49,11 @@ functions given by the sub-system specific method creator through
|
||||
C<mcm> and the data in C<mcm_data> (which is passed by
|
||||
ossl_method_construct()).
|
||||
|
||||
This function assumes that the sub-system method creator implements
|
||||
reference counting and acts accordingly (i.e. it will call the
|
||||
sub-system destruct() method to decrement the reference count when
|
||||
appropriate).
|
||||
|
||||
=head2 Structures
|
||||
|
||||
A central part of constructing a sub-system specific method is to give
|
||||
@@ -82,6 +87,8 @@ The method to be looked up should be identified with data from C<data>
|
||||
(which is the C<mcm_data> that was passed to ossl_construct_method())
|
||||
and the provided property query C<propquery>.
|
||||
|
||||
This function is expected to increment the method's reference count.
|
||||
|
||||
=item put()
|
||||
|
||||
Places the C<method> created by the construct() function (see below)
|
||||
@@ -96,6 +103,8 @@ The method should be associated with the given property definition
|
||||
C<propdef> and any identification data given through C<data> (which is
|
||||
the C<mcm_data> that was passed to ossl_construct_method()).
|
||||
|
||||
This function is expected to increment the C<method>'s reference count.
|
||||
|
||||
=item construct()
|
||||
|
||||
Constructs a sub-system method given a dispatch table C<fns>.
|
||||
@@ -106,9 +115,12 @@ is recommended.
|
||||
If such a reference is kept, the I<provider object> reference counter
|
||||
must be incremented, using ossl_provider_upref().
|
||||
|
||||
This function is expected to set the method's reference count to 1.
|
||||
|
||||
=item desctruct()
|
||||
|
||||
Destruct the given C<method>.
|
||||
Decrement the C<method>'s reference count, and destruct it when
|
||||
the reference count reaches zero.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
ossl_provider_find, ossl_provider_new, ossl_provider_upref,
|
||||
ossl_provider_free, ossl_provider_add_module_location,
|
||||
ossl_provider_activate, ossl_provider_forall_loaded,
|
||||
ossl_provider_set_fallback, ossl_provider_activate,
|
||||
ossl_provider_forall_loaded,
|
||||
ossl_provider_name, ossl_provider_dso,
|
||||
ossl_provider_module_name, ossl_provider_module_path,
|
||||
ossl_provider_teardown, ossl_provider_get_param_types,
|
||||
@@ -23,6 +24,7 @@ ossl_provider_get_params, ossl_provider_query_operation
|
||||
|
||||
/* Setters */
|
||||
int ossl_provider_add_module_location(OSSL_PROVIDER *prov, const char *loc);
|
||||
int ossl_provider_set_fallback(OSSL_PROVIDER *prov);
|
||||
|
||||
/* Load and initialize the Provider */
|
||||
int ossl_provider_activate(OSSL_PROVIDER *prov);
|
||||
@@ -71,7 +73,7 @@ times as ossl_provider_activate() has.
|
||||
|
||||
ossl_provider_find() finds an existing I<provider object> in the
|
||||
I<provider object> store by C<name>.
|
||||
The I<provider object> it finds gets it's reference count
|
||||
The I<provider object> it finds gets its reference count
|
||||
incremented.
|
||||
|
||||
ossl_provider_new() creates a new I<provider object> and stores it in
|
||||
@@ -84,14 +86,20 @@ To indicate a built-in provider, the C<init_function> argument must
|
||||
point at the provider initialization function for that provider.
|
||||
|
||||
ossl_provider_free() decrements a I<provider object>'s reference
|
||||
counter; if it drops to one, the I<provider object> will be
|
||||
inactivated (it's teardown function is called) but kept in the store;
|
||||
if it drops down to zero, the associated module will be unloaded if
|
||||
one was loaded, and the I<provider object> will be freed.
|
||||
counter; if it drops below 2, the I<provider object> is assumed to
|
||||
have fallen out of use and will be inactivated (its teardown function
|
||||
is called); if it drops down to zero, the I<provider object> is
|
||||
assumed to have been taken out of the store, and the associated module
|
||||
will be unloaded if one was loaded, and the I<provider object> will be
|
||||
freed.
|
||||
|
||||
ossl_provider_add_module_location() adds a location to look for a
|
||||
provider module.
|
||||
|
||||
ossl_provider_set_fallback() marks an available provider as fallback.
|
||||
Note that after this call, the I<provider object> pointer that was
|
||||
used can simply be dropped, but not freed.
|
||||
|
||||
ossl_provider_activate() "activates" the provider for the given
|
||||
I<provider object>.
|
||||
What "activates" means depends on what type of I<provider object> it
|
||||
@@ -115,6 +123,8 @@ be located in that module, and called.
|
||||
|
||||
ossl_provider_forall_loaded() iterates over all the currently
|
||||
"activated" providers, and calls C<cb> for each of them.
|
||||
If no providers have been "activated" yet, it tries to activate all
|
||||
available fallback providers and tries another iteration.
|
||||
|
||||
ossl_provider_name() returns the name that was given with
|
||||
ossl_provider_new().
|
||||
@@ -178,8 +188,8 @@ it has been incremented.
|
||||
|
||||
ossl_provider_free() doesn't return any value.
|
||||
|
||||
ossl_provider_add_module_location() and ossl_provider_activate()
|
||||
return 1 on success, or 0 on error.
|
||||
ossl_provider_add_module_location(), ossl_provider_set_fallback() and
|
||||
ossl_provider_activate() return 1 on success, or 0 on error.
|
||||
|
||||
ossl_provider_name(), ossl_provider_dso(),
|
||||
ossl_provider_module_name(), and ossl_provider_module_path() return a
|
||||
|
||||
Reference in New Issue
Block a user