openssl/providers/implementations/keymgmt/dsa_kmgmt.c
Shane Lontis 38145fba0a Fix DSA/DH so that legacy keys can still be generated by the default provider
Fixes #12589

The 'type' parameter needed to be propagated to the ffc params during keygen,
so that the simple validation of params done during keygen can handle legacy keys for the default provider.
The fips provider ignores this change and only allows fips186-4 approved sizes.

Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/12623)
2020-08-17 23:40:20 +10:00

599 lines
19 KiB
C

/*
* Copyright 2019-2020 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
*/
/*
* DSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "e_os.h" /* strcasecmp */
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include "prov/providercommon.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "crypto/dsa.h"
#include "internal/sizes.h"
#include "internal/nelem.h"
#include "internal/param_build_set.h"
static OSSL_FUNC_keymgmt_new_fn dsa_newdata;
static OSSL_FUNC_keymgmt_free_fn dsa_freedata;
static OSSL_FUNC_keymgmt_gen_init_fn dsa_gen_init;
static OSSL_FUNC_keymgmt_gen_set_template_fn dsa_gen_set_template;
static OSSL_FUNC_keymgmt_gen_set_params_fn dsa_gen_set_params;
static OSSL_FUNC_keymgmt_gen_settable_params_fn dsa_gen_settable_params;
static OSSL_FUNC_keymgmt_gen_fn dsa_gen;
static OSSL_FUNC_keymgmt_gen_cleanup_fn dsa_gen_cleanup;
static OSSL_FUNC_keymgmt_load_fn dsa_load;
static OSSL_FUNC_keymgmt_get_params_fn dsa_get_params;
static OSSL_FUNC_keymgmt_gettable_params_fn dsa_gettable_params;
static OSSL_FUNC_keymgmt_has_fn dsa_has;
static OSSL_FUNC_keymgmt_match_fn dsa_match;
static OSSL_FUNC_keymgmt_validate_fn dsa_validate;
static OSSL_FUNC_keymgmt_import_fn dsa_import;
static OSSL_FUNC_keymgmt_import_types_fn dsa_import_types;
static OSSL_FUNC_keymgmt_export_fn dsa_export;
static OSSL_FUNC_keymgmt_export_types_fn dsa_export_types;
#define DSA_DEFAULT_MD "SHA256"
#define DSA_POSSIBLE_SELECTIONS \
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
struct dsa_gen_ctx {
OPENSSL_CTX *libctx;
FFC_PARAMS *ffc_params;
int selection;
/* All these parameters are used for parameter generation only */
size_t pbits;
size_t qbits;
unsigned char *seed; /* optional FIPS186-4 param for testing */
size_t seedlen;
int gindex; /* optional FIPS186-4 generator index (ignored if -1) */
int gen_type; /* DSA_PARAMGEN_TYPE_FIPS_186_2 or DSA_PARAMGEN_TYPE_FIPS_186_4 */
int pcounter;
int hindex;
const char *mdname;
const char *mdprops;
OSSL_CALLBACK *cb;
void *cbarg;
};
typedef struct dh_name2id_st{
const char *name;
int id;
} DSA_GENTYPE_NAME2ID;
static const DSA_GENTYPE_NAME2ID dsatype2id[]=
{
{ "default", DSA_PARAMGEN_TYPE_FIPS_186_4 },
{ "fips186_4", DSA_PARAMGEN_TYPE_FIPS_186_4 },
{ "fips186_2", DSA_PARAMGEN_TYPE_FIPS_186_2 },
};
static int dsa_gen_type_name2id(const char *name)
{
size_t i;
for (i = 0; i < OSSL_NELEM(dsatype2id); ++i) {
if (strcasecmp(dsatype2id[i].name, name) == 0)
return dsatype2id[i].id;
}
return -1;
}
static int dsa_key_todata(DSA *dsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
{
const BIGNUM *priv = NULL, *pub = NULL;
if (dsa == NULL)
return 0;
DSA_get0_key(dsa, &pub, &priv);
if (priv != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
return 0;
if (pub != NULL
&& !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
return 0;
return 1;
}
static void *dsa_newdata(void *provctx)
{
return dsa_new_with_ctx(PROV_LIBRARY_CONTEXT_OF(provctx));
}
static void dsa_freedata(void *keydata)
{
DSA_free(keydata);
}
static int dsa_has(void *keydata, int selection)
{
DSA *dsa = keydata;
int ok = 0;
if (dsa != NULL) {
if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && (DSA_get0_pub_key(dsa) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && (DSA_get0_priv_key(dsa) != NULL);
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
}
return ok;
}
static int dsa_match(const void *keydata1, const void *keydata2, int selection)
{
const DSA *dsa1 = keydata1;
const DSA *dsa2 = keydata2;
int ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok
&& BN_cmp(DSA_get0_pub_key(dsa1), DSA_get0_pub_key(dsa2)) == 0;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok
&& BN_cmp(DSA_get0_priv_key(dsa1), DSA_get0_priv_key(dsa2)) == 0;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
FFC_PARAMS *dsaparams1 = dsa_get0_params((DSA *)dsa1);
FFC_PARAMS *dsaparams2 = dsa_get0_params((DSA *)dsa2);
ok = ok && ffc_params_cmp(dsaparams1, dsaparams2, 1);
}
return ok;
}
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
{
DSA *dsa = keydata;
int ok = 1;
if (dsa == NULL)
return 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return 0;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && dsa_ffc_params_fromdata(dsa, params);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && dsa_key_fromdata(dsa, params);
return ok;
}
static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
void *cbarg)
{
DSA *dsa = keydata;
OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
OSSL_PARAM *params = NULL;
int ok = 1;
if (dsa == NULL)
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
ok = ok && ffc_params_todata(dsa_get0_params(dsa), tmpl, NULL);
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
ok = ok && dsa_key_todata(dsa, tmpl, NULL);
if (!ok
|| (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;;
ok = param_cb(params, cbarg);
OSSL_PARAM_BLD_free_params(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return ok;
}
/* IMEXPORT = IMPORT + EXPORT */
# define DSA_IMEXPORTABLE_PARAMETERS \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0)
# define DSA_IMEXPORTABLE_PUBLIC_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
# define DSA_IMEXPORTABLE_PRIVATE_KEY \
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
static const OSSL_PARAM dsa_all_types[] = {
DSA_IMEXPORTABLE_PARAMETERS,
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM dsa_parameter_types[] = {
DSA_IMEXPORTABLE_PARAMETERS,
OSSL_PARAM_END
};
static const OSSL_PARAM dsa_key_types[] = {
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM *dsa_types[] = {
NULL, /* Index 0 = none of them */
dsa_parameter_types, /* Index 1 = parameter types */
dsa_key_types, /* Index 2 = key types */
dsa_all_types /* Index 3 = 1 + 2 */
};
static const OSSL_PARAM *dsa_imexport_types(int selection)
{
int type_select = 0;
if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
type_select += 1;
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
type_select += 2;
return dsa_types[type_select];
}
static const OSSL_PARAM *dsa_import_types(int selection)
{
return dsa_imexport_types(selection);
}
static const OSSL_PARAM *dsa_export_types(int selection)
{
return dsa_imexport_types(selection);
}
static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
{
DSA *dsa = key;
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_bits(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_security_bits(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, DSA_size(dsa)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
&& !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD))
return 0;
return ffc_params_todata(dsa_get0_params(dsa), NULL, params)
&& dsa_key_todata(dsa, NULL, params);
}
static const OSSL_PARAM dsa_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
DSA_IMEXPORTABLE_PARAMETERS,
DSA_IMEXPORTABLE_PUBLIC_KEY,
DSA_IMEXPORTABLE_PRIVATE_KEY,
OSSL_PARAM_END
};
static const OSSL_PARAM *dsa_gettable_params(void *provctx)
{
return dsa_params;
}
static int dsa_validate_domparams(DSA *dsa)
{
int status = 0;
return dsa_check_params(dsa, &status);
}
static int dsa_validate_public(DSA *dsa)
{
int status = 0;
const BIGNUM *pub_key = NULL;
DSA_get0_key(dsa, &pub_key, NULL);
if (pub_key == NULL)
return 0;
return dsa_check_pub_key(dsa, pub_key, &status);
}
static int dsa_validate_private(DSA *dsa)
{
int status = 0;
const BIGNUM *priv_key = NULL;
DSA_get0_key(dsa, NULL, &priv_key);
if (priv_key == NULL)
return 0;
return dsa_check_priv_key(dsa, priv_key, &status);
}
static int dsa_validate(void *keydata, int selection)
{
DSA *dsa = keydata;
int ok = 0;
if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
ok = 1;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ok = ok && dsa_validate_domparams(dsa);
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
ok = ok && dsa_validate_public(dsa);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && dsa_validate_private(dsa);
/* If the whole key is selected, we do a pairwise validation */
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
== OSSL_KEYMGMT_SELECT_KEYPAIR)
ok = ok && dsa_check_pairwise(dsa);
return ok;
}
static void *dsa_gen_init(void *provctx, int selection)
{
OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
struct dsa_gen_ctx *gctx = NULL;
if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
return NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->selection = selection;
gctx->libctx = libctx;
gctx->pbits = 2048;
gctx->qbits = 224;
gctx->gen_type = DSA_PARAMGEN_TYPE_FIPS_186_4;
gctx->gindex = -1;
gctx->pcounter = -1;
gctx->hindex = 0;
}
return gctx;
}
static int dsa_gen_set_template(void *genctx, void *templ)
{
struct dsa_gen_ctx *gctx = genctx;
DSA *dsa = templ;
if (gctx == NULL || dsa == NULL)
return 0;
gctx->ffc_params = dsa_get0_params(dsa);
return 1;
}
static int dsa_set_gen_seed(struct dsa_gen_ctx *gctx, unsigned char *seed,
size_t seedlen)
{
OPENSSL_clear_free(gctx->seed, gctx->seedlen);
gctx->seed = NULL;
gctx->seedlen = 0;
if (seed != NULL && seedlen > 0) {
gctx->seed = OPENSSL_memdup(seed, seedlen);
if (gctx->seed == NULL)
return 0;
gctx->seedlen = seedlen;
}
return 1;
}
static int dsa_gen_set_params(void *genctx, const OSSL_PARAM params[])
{
struct dsa_gen_ctx *gctx = genctx;
const OSSL_PARAM *p;
if (gctx == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING
|| ((gctx->gen_type = dsa_gen_type_name2id(p->data)) == -1)) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->gindex))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->pcounter))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
if (p != NULL
&& !OSSL_PARAM_get_int(p, &gctx->hindex))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
if (p != NULL
&& (p->data_type != OSSL_PARAM_OCTET_STRING
|| !dsa_set_gen_seed(gctx, p->data, p->data_size)))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
&& !OSSL_PARAM_get_size_t(p, &gctx->pbits))
return 0;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
&& !OSSL_PARAM_get_size_t(p, &gctx->qbits))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
gctx->mdname = p->data;
}
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
return 0;
gctx->mdprops = p->data;
}
return 1;
}
static const OSSL_PARAM *dsa_gen_settable_params(void *provctx)
{
static OSSL_PARAM settable[] = {
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
OSSL_PARAM_END
};
return settable;
}
static int dsa_gencb(int p, int n, BN_GENCB *cb)
{
struct dsa_gen_ctx *gctx = BN_GENCB_get_arg(cb);
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
return gctx->cb(params, gctx->cbarg);
}
static void *dsa_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
{
struct dsa_gen_ctx *gctx = genctx;
DSA *dsa = NULL;
BN_GENCB *gencb = NULL;
int ret = 0;
FFC_PARAMS *ffc;
if (gctx == NULL)
return NULL;
dsa = dsa_new_with_ctx(gctx->libctx);
if (dsa == NULL)
return NULL;
gctx->cb = osslcb;
gctx->cbarg = cbarg;
gencb = BN_GENCB_new();
if (gencb != NULL)
BN_GENCB_set(gencb, dsa_gencb, genctx);
ffc = dsa_get0_params(dsa);
/* Copy the template value if one was passed */
if (gctx->ffc_params != NULL
&& !ffc_params_copy(ffc, gctx->ffc_params))
goto end;
if (gctx->seed != NULL
&& !ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
goto end;
if (gctx->gindex != -1) {
ffc_params_set_gindex(ffc, gctx->gindex);
if (gctx->pcounter != -1)
ffc_params_set_pcounter(ffc, gctx->pcounter);
} else if (gctx->hindex != 0) {
ffc_params_set_h(ffc, gctx->hindex);
}
if (gctx->mdname != NULL) {
if (!ffc_set_digest(ffc, gctx->mdname, gctx->mdprops))
goto end;
}
if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
if (dsa_generate_ffc_parameters(dsa, gctx->gen_type,
gctx->pbits, gctx->qbits,
gencb) <= 0)
goto end;
}
ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,
gctx->gen_type == DSA_PARAMGEN_TYPE_FIPS_186_2);
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
if (ffc->p == NULL
|| ffc->q == NULL
|| ffc->g == NULL)
goto end;
if (DSA_generate_key(dsa) <= 0)
goto end;
}
ret = 1;
end:
if (ret <= 0) {
DSA_free(dsa);
dsa = NULL;
}
BN_GENCB_free(gencb);
return dsa;
}
static void dsa_gen_cleanup(void *genctx)
{
struct dsa_gen_ctx *gctx = genctx;
if (gctx == NULL)
return;
OPENSSL_clear_free(gctx->seed, gctx->seedlen);
OPENSSL_free(gctx);
}
void *dsa_load(const void *reference, size_t reference_sz)
{
DSA *dsa = NULL;
if (reference_sz == sizeof(dsa)) {
/* The contents of the reference is the address to our object */
dsa = *(DSA **)reference;
/* We grabbed, so we detach it */
*(DSA **)reference = NULL;
return dsa;
}
return NULL;
}
const OSSL_DISPATCH dsa_keymgmt_functions[] = {
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dsa_gen_init },
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dsa_gen_set_template },
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dsa_gen_set_params },
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
(void (*)(void))dsa_gen_settable_params },
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dsa_gen },
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dsa_gen_cleanup },
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dsa_load },
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dsa_validate },
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dsa_export_types },
{ 0, NULL }
};