openssl/crypto/evp/keymgmt_meth.c
Pauli 16ff70a58c Remove the _fetch_by_number functions
These functions are unused and untested.  They are also implemented rather
inefficiently.  If we ever needed them in the future, they'd almost surely
need to be rewritten more efficiently.

Fixes #18227

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18237)
2022-05-06 10:38:55 +10:00

486 lines
16 KiB
C

/*
* Copyright 2019-2021 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 <openssl/crypto.h>
#include <openssl/core_dispatch.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/provider.h"
#include "internal/refcount.h"
#include "internal/core.h"
#include "crypto/evp.h"
#include "evp_local.h"
static void *keymgmt_new(void)
{
EVP_KEYMGMT *keymgmt = NULL;
if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
|| (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
EVP_KEYMGMT_free(keymgmt);
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
keymgmt->refcnt = 1;
return keymgmt;
}
static void *keymgmt_from_algorithm(int name_id,
const OSSL_ALGORITHM *algodef,
OSSL_PROVIDER *prov)
{
const OSSL_DISPATCH *fns = algodef->implementation;
EVP_KEYMGMT *keymgmt = NULL;
int setparamfncnt = 0, getparamfncnt = 0;
int setgenparamfncnt = 0;
int importfncnt = 0, exportfncnt = 0;
if ((keymgmt = keymgmt_new()) == NULL)
return NULL;
keymgmt->name_id = name_id;
if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
EVP_KEYMGMT_free(keymgmt);
return NULL;
}
keymgmt->description = algodef->algorithm_description;
for (; fns->function_id != 0; fns++) {
switch (fns->function_id) {
case OSSL_FUNC_KEYMGMT_NEW:
if (keymgmt->new == NULL)
keymgmt->new = OSSL_FUNC_keymgmt_new(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_INIT:
if (keymgmt->gen_init == NULL)
keymgmt->gen_init = OSSL_FUNC_keymgmt_gen_init(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
if (keymgmt->gen_set_template == NULL)
keymgmt->gen_set_template =
OSSL_FUNC_keymgmt_gen_set_template(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
if (keymgmt->gen_set_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_set_params =
OSSL_FUNC_keymgmt_gen_set_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
if (keymgmt->gen_settable_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_settable_params =
OSSL_FUNC_keymgmt_gen_settable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN:
if (keymgmt->gen == NULL)
keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
if (keymgmt->gen_cleanup == NULL)
keymgmt->gen_cleanup = OSSL_FUNC_keymgmt_gen_cleanup(fns);
break;
case OSSL_FUNC_KEYMGMT_FREE:
if (keymgmt->free == NULL)
keymgmt->free = OSSL_FUNC_keymgmt_free(fns);
break;
case OSSL_FUNC_KEYMGMT_LOAD:
if (keymgmt->load == NULL)
keymgmt->load = OSSL_FUNC_keymgmt_load(fns);
break;
case OSSL_FUNC_KEYMGMT_GET_PARAMS:
if (keymgmt->get_params == NULL) {
getparamfncnt++;
keymgmt->get_params = OSSL_FUNC_keymgmt_get_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
if (keymgmt->gettable_params == NULL) {
getparamfncnt++;
keymgmt->gettable_params =
OSSL_FUNC_keymgmt_gettable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_SET_PARAMS:
if (keymgmt->set_params == NULL) {
setparamfncnt++;
keymgmt->set_params = OSSL_FUNC_keymgmt_set_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
if (keymgmt->settable_params == NULL) {
setparamfncnt++;
keymgmt->settable_params =
OSSL_FUNC_keymgmt_settable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
if (keymgmt->query_operation_name == NULL)
keymgmt->query_operation_name =
OSSL_FUNC_keymgmt_query_operation_name(fns);
break;
case OSSL_FUNC_KEYMGMT_HAS:
if (keymgmt->has == NULL)
keymgmt->has = OSSL_FUNC_keymgmt_has(fns);
break;
case OSSL_FUNC_KEYMGMT_DUP:
if (keymgmt->dup == NULL)
keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
break;
case OSSL_FUNC_KEYMGMT_VALIDATE:
if (keymgmt->validate == NULL)
keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
break;
case OSSL_FUNC_KEYMGMT_MATCH:
if (keymgmt->match == NULL)
keymgmt->match = OSSL_FUNC_keymgmt_match(fns);
break;
case OSSL_FUNC_KEYMGMT_IMPORT:
if (keymgmt->import == NULL) {
importfncnt++;
keymgmt->import = OSSL_FUNC_keymgmt_import(fns);
}
break;
case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
if (keymgmt->import_types == NULL) {
importfncnt++;
keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns);
}
break;
case OSSL_FUNC_KEYMGMT_EXPORT:
if (keymgmt->export == NULL) {
exportfncnt++;
keymgmt->export = OSSL_FUNC_keymgmt_export(fns);
}
break;
case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
if (keymgmt->export_types == NULL) {
exportfncnt++;
keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns);
}
break;
}
}
/*
* Try to check that the method is sensible.
* At least one constructor and the destructor are MANDATORY
* The functions 'has' is MANDATORY
* It makes no sense being able to free stuff if you can't create it.
* It makes no sense providing OSSL_PARAM descriptors for import and
* export if you can't import or export.
*/
if (keymgmt->free == NULL
|| (keymgmt->new == NULL
&& keymgmt->gen == NULL
&& keymgmt->load == NULL)
|| keymgmt->has == NULL
|| (getparamfncnt != 0 && getparamfncnt != 2)
|| (setparamfncnt != 0 && setparamfncnt != 2)
|| (setgenparamfncnt != 0 && setgenparamfncnt != 2)
|| (importfncnt != 0 && importfncnt != 2)
|| (exportfncnt != 0 && exportfncnt != 2)
|| (keymgmt->gen != NULL
&& (keymgmt->gen_init == NULL
|| keymgmt->gen_cleanup == NULL))) {
EVP_KEYMGMT_free(keymgmt);
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
}
keymgmt->prov = prov;
if (prov != NULL)
ossl_provider_up_ref(prov);
return keymgmt;
}
EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
const char *name,
const char *properties)
{
return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYMGMT,
name, properties,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
const char *properties)
{
return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
return 1;
}
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
{
int ref = 0;
if (keymgmt == NULL)
return;
CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock);
if (ref > 0)
return;
OPENSSL_free(keymgmt->type_name);
ossl_provider_free(keymgmt->prov);
CRYPTO_THREAD_lock_free(keymgmt->lock);
OPENSSL_free(keymgmt);
}
const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->prov;
}
int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->name_id;
}
const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->description;
}
const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt)
{
return keymgmt->type_name;
}
int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
{
return evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
}
void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
void *arg)
{
evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
(void (*)(void *, void *))fn, arg,
keymgmt_from_algorithm,
(int (*)(void *))EVP_KEYMGMT_up_ref,
(void (*)(void *))EVP_KEYMGMT_free);
}
int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
void (*fn)(const char *name, void *data),
void *data)
{
if (keymgmt->prov != NULL)
return evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
return 1;
}
/*
* Internal API that interfaces with the method function pointers
*/
void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
/*
* 'new' is currently mandatory on its own, but when new
* constructors appear, it won't be quite as mandatory,
* so we have a check for future cases.
*/
if (keymgmt->new == NULL)
return NULL;
return keymgmt->new(provctx);
}
void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
{
/* This is mandatory, no need to check for its presence */
keymgmt->free(keydata);
}
void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
const OSSL_PARAM params[])
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gen_init == NULL)
return NULL;
return keymgmt->gen_init(provctx, selection, params);
}
int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
void *template)
{
/*
* It's arguable if we actually should return success in this case, as
* it allows the caller to set a template key, which is then ignored.
* However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
* so we do this in the interest of backward compatibility.
*/
if (keymgmt->gen_set_template == NULL)
return 1;
return keymgmt->gen_set_template(genctx, template);
}
int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
const OSSL_PARAM params[])
{
if (keymgmt->gen_set_params == NULL)
return 0;
return keymgmt->gen_set_params(genctx, params);
}
const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gen_settable_params == NULL)
return NULL;
return keymgmt->gen_settable_params(NULL, provctx);
}
void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
OSSL_CALLBACK *cb, void *cbarg)
{
if (keymgmt->gen == NULL)
return NULL;
return keymgmt->gen(genctx, cb, cbarg);
}
void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
{
if (keymgmt->gen != NULL)
keymgmt->gen_cleanup(genctx);
}
int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt)
{
return keymgmt != NULL && keymgmt->load != NULL;
}
void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
const void *objref, size_t objref_sz)
{
if (evp_keymgmt_has_load(keymgmt))
return keymgmt->load(objref, objref_sz);
return NULL;
}
int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
OSSL_PARAM params[])
{
if (keymgmt->get_params == NULL)
return 1;
return keymgmt->get_params(keydata, params);
}
const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->gettable_params == NULL)
return NULL;
return keymgmt->gettable_params(provctx);
}
int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
const OSSL_PARAM params[])
{
if (keymgmt->set_params == NULL)
return 1;
return keymgmt->set_params(keydata, params);
}
const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
if (keymgmt->settable_params == NULL)
return NULL;
return keymgmt->settable_params(provctx);
}
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
{
/* This is mandatory, no need to check for its presence */
return keymgmt->has(keydata, selection);
}
int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, int checktype)
{
/* We assume valid if the implementation doesn't have a function */
if (keymgmt->validate == NULL)
return 1;
return keymgmt->validate(keydata, selection, checktype);
}
int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
const void *keydata1, const void *keydata2,
int selection)
{
/* We assume no match if the implementation doesn't have a function */
if (keymgmt->match == NULL)
return 0;
return keymgmt->match(keydata1, keydata2, selection);
}
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, const OSSL_PARAM params[])
{
if (keymgmt->import == NULL)
return 0;
return keymgmt->import(keydata, selection, params);
}
const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
if (keymgmt->import_types == NULL)
return NULL;
return keymgmt->import_types(selection);
}
int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
int selection, OSSL_CALLBACK *param_cb, void *cbarg)
{
if (keymgmt->export == NULL)
return 0;
return keymgmt->export(keydata, selection, param_cb, cbarg);
}
const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
int selection)
{
if (keymgmt->export_types == NULL)
return NULL;
return keymgmt->export_types(selection);
}
void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
int selection)
{
/* We assume no dup if the implementation doesn't have a function */
if (keymgmt->dup == NULL)
return NULL;
return keymgmt->dup(keydata_from, selection);
}