2019-02-25 08:59:02 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* https://www.openssl.org/source/license.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include <openssl/core.h>
|
|
|
|
#include "internal/cryptlib.h"
|
|
|
|
#include "internal/core.h"
|
|
|
|
#include "internal/property.h"
|
|
|
|
#include "internal/provider.h"
|
|
|
|
|
|
|
|
struct construct_data_st {
|
|
|
|
OPENSSL_CTX *libctx;
|
|
|
|
OSSL_METHOD_STORE *store;
|
|
|
|
int operation_id;
|
|
|
|
int force_store;
|
|
|
|
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
|
|
|
|
void *mcm_data;
|
|
|
|
};
|
|
|
|
|
2020-05-15 21:56:05 +08:00
|
|
|
static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
|
|
|
|
int operation_id, void *cbdata,
|
|
|
|
int *result)
|
|
|
|
{
|
|
|
|
if (!ossl_assert(result != NULL)) {
|
|
|
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ossl_provider_test_operation_bit(provider, operation_id, result))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The result we get tells if methods have already been constructed.
|
|
|
|
* However, we want to tell whether construction should happen (true)
|
|
|
|
* or not (false), which is the opposite of what we got.
|
|
|
|
*/
|
|
|
|
*result = !*result;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
|
|
|
|
int operation_id, int no_store,
|
|
|
|
void *cbdata, int *result)
|
|
|
|
{
|
|
|
|
if (!ossl_assert(result != NULL)) {
|
|
|
|
ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result = 1;
|
|
|
|
return no_store != 0
|
|
|
|
|| ossl_provider_set_operation_bit(provider, operation_id);
|
|
|
|
}
|
|
|
|
|
2019-07-11 05:14:03 +08:00
|
|
|
static void ossl_method_construct_this(OSSL_PROVIDER *provider,
|
|
|
|
const OSSL_ALGORITHM *algo,
|
|
|
|
int no_store, void *cbdata)
|
2019-02-25 08:59:02 +08:00
|
|
|
{
|
|
|
|
struct construct_data_st *data = cbdata;
|
2019-07-11 05:14:03 +08:00
|
|
|
void *method = NULL;
|
2019-02-25 08:59:02 +08:00
|
|
|
|
2019-11-19 16:55:56 +08:00
|
|
|
if ((method = data->mcm->construct(algo, provider, data->mcm_data))
|
|
|
|
== NULL)
|
2019-07-11 05:14:03 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note regarding putting the method in stores:
|
|
|
|
*
|
|
|
|
* we don't need to care if it actually got in or not here.
|
|
|
|
* If it didn't get in, it will simply not be available when
|
|
|
|
* ossl_method_construct() tries to get it from the store.
|
|
|
|
*
|
|
|
|
* It is *expected* that the put function increments the refcnt
|
|
|
|
* of the passed method.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (data->force_store || !no_store) {
|
2019-03-15 04:51:50 +08:00
|
|
|
/*
|
2019-07-11 05:14:03 +08:00
|
|
|
* If we haven't been told not to store,
|
|
|
|
* add to the global store
|
2019-03-15 04:51:50 +08:00
|
|
|
*/
|
2019-08-21 16:08:44 +08:00
|
|
|
data->mcm->put(data->libctx, NULL, method, provider,
|
2019-05-23 09:36:21 +08:00
|
|
|
data->operation_id, algo->algorithm_names,
|
2019-07-11 05:14:03 +08:00
|
|
|
algo->property_definition, data->mcm_data);
|
2019-02-25 08:59:02 +08:00
|
|
|
}
|
|
|
|
|
2019-08-21 16:08:44 +08:00
|
|
|
data->mcm->put(data->libctx, data->store, method, provider,
|
2019-05-23 09:36:21 +08:00
|
|
|
data->operation_id, algo->algorithm_names,
|
2019-08-21 16:08:44 +08:00
|
|
|
algo->property_definition, data->mcm_data);
|
2019-07-11 05:14:03 +08:00
|
|
|
|
|
|
|
/* refcnt-- because we're dropping the reference */
|
|
|
|
data->mcm->destruct(method, data->mcm_data);
|
2019-02-25 08:59:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
|
|
|
|
int force_store,
|
|
|
|
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
|
|
|
|
{
|
|
|
|
void *method = NULL;
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
if ((method = mcm->get(libctx, NULL, mcm_data)) == NULL) {
|
2019-02-25 08:59:02 +08:00
|
|
|
struct construct_data_st cbdata;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have a temporary store to be able to easily search among new
|
|
|
|
* items, or items that should find themselves in the global store.
|
|
|
|
*/
|
2019-05-01 18:02:43 +08:00
|
|
|
if ((cbdata.store = mcm->alloc_tmp_store(libctx)) == NULL)
|
2019-02-25 08:59:02 +08:00
|
|
|
goto fin;
|
|
|
|
|
|
|
|
cbdata.libctx = libctx;
|
|
|
|
cbdata.operation_id = operation_id;
|
|
|
|
cbdata.force_store = force_store;
|
|
|
|
cbdata.mcm = mcm;
|
|
|
|
cbdata.mcm_data = mcm_data;
|
2019-07-11 05:14:03 +08:00
|
|
|
ossl_algorithm_do_all(libctx, operation_id, NULL,
|
2020-05-15 21:56:05 +08:00
|
|
|
ossl_method_construct_precondition,
|
|
|
|
ossl_method_construct_this,
|
|
|
|
ossl_method_construct_postcondition,
|
|
|
|
&cbdata);
|
2019-02-25 08:59:02 +08:00
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
method = mcm->get(libctx, cbdata.store, mcm_data);
|
2019-02-25 08:59:02 +08:00
|
|
|
mcm->dealloc_tmp_store(cbdata.store);
|
|
|
|
}
|
|
|
|
|
|
|
|
fin:
|
|
|
|
return method;
|
|
|
|
}
|