Path: blob/main/crypto/openssl/providers/implementations/keymgmt/dh_kmgmt.c
48292 views
/*1* Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* DH low level APIs are deprecated for public use, but still ok for11* internal use.12*/13#include "internal/deprecated.h"14#include "internal/common.h"1516#include <string.h> /* strcmp */17#include <openssl/core_dispatch.h>18#include <openssl/core_names.h>19#include <openssl/bn.h>20#include <openssl/err.h>21#include <openssl/self_test.h>22#include "prov/implementations.h"23#include "prov/providercommon.h"24#include "prov/provider_ctx.h"25#include "crypto/dh.h"26#include "internal/fips.h"27#include "internal/sizes.h"2829static OSSL_FUNC_keymgmt_new_fn dh_newdata;30static OSSL_FUNC_keymgmt_free_fn dh_freedata;31static OSSL_FUNC_keymgmt_gen_init_fn dh_gen_init;32static OSSL_FUNC_keymgmt_gen_init_fn dhx_gen_init;33static OSSL_FUNC_keymgmt_gen_set_template_fn dh_gen_set_template;34static OSSL_FUNC_keymgmt_gen_set_params_fn dh_gen_set_params;35static OSSL_FUNC_keymgmt_gen_settable_params_fn dh_gen_settable_params;36static OSSL_FUNC_keymgmt_gen_fn dh_gen;37static OSSL_FUNC_keymgmt_gen_cleanup_fn dh_gen_cleanup;38static OSSL_FUNC_keymgmt_load_fn dh_load;39static OSSL_FUNC_keymgmt_get_params_fn dh_get_params;40static OSSL_FUNC_keymgmt_gettable_params_fn dh_gettable_params;41static OSSL_FUNC_keymgmt_set_params_fn dh_set_params;42static OSSL_FUNC_keymgmt_settable_params_fn dh_settable_params;43static OSSL_FUNC_keymgmt_has_fn dh_has;44static OSSL_FUNC_keymgmt_match_fn dh_match;45static OSSL_FUNC_keymgmt_validate_fn dh_validate;46static OSSL_FUNC_keymgmt_import_fn dh_import;47static OSSL_FUNC_keymgmt_import_types_fn dh_import_types;48static OSSL_FUNC_keymgmt_export_fn dh_export;49static OSSL_FUNC_keymgmt_export_types_fn dh_export_types;50static OSSL_FUNC_keymgmt_dup_fn dh_dup;5152#define DH_POSSIBLE_SELECTIONS \53(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)5455struct dh_gen_ctx {56OSSL_LIB_CTX *libctx;5758FFC_PARAMS *ffc_params;59int selection;60/* All these parameters are used for parameter generation only */61/* If there is a group name then the remaining parameters are not needed */62int group_nid;63size_t pbits;64size_t qbits;65unsigned char *seed; /* optional FIPS186-4 param for testing */66size_t seedlen;67int gindex; /* optional FIPS186-4 generator index (ignored if -1) */68int gen_type; /* see dhtype2id */69int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */70int pcounter;71int hindex;72int priv_len;7374char *mdname;75char *mdprops;76OSSL_CALLBACK *cb;77void *cbarg;78int dh_type;79};8081static int dh_gen_type_name2id_w_default(const char *name, int type)82{83if (strcmp(name, "default") == 0) {84#ifdef FIPS_MODULE85if (type == DH_FLAG_TYPE_DHX)86return DH_PARAMGEN_TYPE_FIPS_186_4;8788return DH_PARAMGEN_TYPE_GROUP;89#else90if (type == DH_FLAG_TYPE_DHX)91return DH_PARAMGEN_TYPE_FIPS_186_2;9293return DH_PARAMGEN_TYPE_GENERATOR;94#endif95}9697return ossl_dh_gen_type_name2id(name, type);98}99100static void *dh_newdata(void *provctx)101{102DH *dh = NULL;103104if (ossl_prov_is_running()) {105dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));106if (dh != NULL) {107DH_clear_flags(dh, DH_FLAG_TYPE_MASK);108DH_set_flags(dh, DH_FLAG_TYPE_DH);109}110}111return dh;112}113114static void *dhx_newdata(void *provctx)115{116DH *dh = NULL;117118dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));119if (dh != NULL) {120DH_clear_flags(dh, DH_FLAG_TYPE_MASK);121DH_set_flags(dh, DH_FLAG_TYPE_DHX);122}123return dh;124}125126static void dh_freedata(void *keydata)127{128DH_free(keydata);129}130131static int dh_has(const void *keydata, int selection)132{133const DH *dh = keydata;134int ok = 1;135136if (!ossl_prov_is_running() || dh == NULL)137return 0;138if ((selection & DH_POSSIBLE_SELECTIONS) == 0)139return 1; /* the selection is not missing */140141if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)142ok = ok && (DH_get0_pub_key(dh) != NULL);143if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)144ok = ok && (DH_get0_priv_key(dh) != NULL);145if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)146ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);147return ok;148}149150static int dh_match(const void *keydata1, const void *keydata2, int selection)151{152const DH *dh1 = keydata1;153const DH *dh2 = keydata2;154int ok = 1;155156if (!ossl_prov_is_running())157return 0;158159if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {160int key_checked = 0;161162if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {163const BIGNUM *pa = DH_get0_pub_key(dh1);164const BIGNUM *pb = DH_get0_pub_key(dh2);165166if (pa != NULL && pb != NULL) {167ok = ok && BN_cmp(pa, pb) == 0;168key_checked = 1;169}170}171if (!key_checked172&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {173const BIGNUM *pa = DH_get0_priv_key(dh1);174const BIGNUM *pb = DH_get0_priv_key(dh2);175176if (pa != NULL && pb != NULL) {177ok = ok && BN_cmp(pa, pb) == 0;178key_checked = 1;179}180}181ok = ok && key_checked;182}183if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {184FFC_PARAMS *dhparams1 = ossl_dh_get0_params((DH *)dh1);185FFC_PARAMS *dhparams2 = ossl_dh_get0_params((DH *)dh2);186187ok = ok && ossl_ffc_params_cmp(dhparams1, dhparams2, 1);188}189return ok;190}191192static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])193{194DH *dh = keydata;195int ok = 1;196197if (!ossl_prov_is_running() || dh == NULL)198return 0;199200if ((selection & DH_POSSIBLE_SELECTIONS) == 0)201return 0;202203/* a key without parameters is meaningless */204ok = ok && ossl_dh_params_fromdata(dh, params);205206if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {207int include_private =208selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;209210ok = ok && ossl_dh_key_fromdata(dh, params, include_private);211}212213return ok;214}215216static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,217void *cbarg)218{219DH *dh = keydata;220OSSL_PARAM_BLD *tmpl = NULL;221OSSL_PARAM *params = NULL;222int ok = 1;223224if (!ossl_prov_is_running() || dh == NULL)225return 0;226227if ((selection & DH_POSSIBLE_SELECTIONS) == 0)228return 0;229230tmpl = OSSL_PARAM_BLD_new();231if (tmpl == NULL)232return 0;233234if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)235ok = ok && ossl_dh_params_todata(dh, tmpl, NULL);236237if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {238int include_private =239selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;240241ok = ok && ossl_dh_key_todata(dh, tmpl, NULL, include_private);242}243244if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {245ok = 0;246goto err;247}248249ok = param_cb(params, cbarg);250OSSL_PARAM_free(params);251err:252OSSL_PARAM_BLD_free(tmpl);253return ok;254}255256/* IMEXPORT = IMPORT + EXPORT */257258# define DH_IMEXPORTABLE_PARAMETERS \259OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0), \260OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0), \261OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0), \262OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0), \263OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL), \264OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL), \265OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL), \266OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL), \267OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0), \268OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0)269# define DH_IMEXPORTABLE_PUBLIC_KEY \270OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)271# define DH_IMEXPORTABLE_PRIVATE_KEY \272OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)273static const OSSL_PARAM dh_all_types[] = {274DH_IMEXPORTABLE_PARAMETERS,275DH_IMEXPORTABLE_PUBLIC_KEY,276DH_IMEXPORTABLE_PRIVATE_KEY,277OSSL_PARAM_END278};279static const OSSL_PARAM dh_parameter_types[] = {280DH_IMEXPORTABLE_PARAMETERS,281OSSL_PARAM_END282};283static const OSSL_PARAM dh_key_types[] = {284DH_IMEXPORTABLE_PUBLIC_KEY,285DH_IMEXPORTABLE_PRIVATE_KEY,286OSSL_PARAM_END287};288static const OSSL_PARAM *dh_types[] = {289NULL, /* Index 0 = none of them */290dh_parameter_types, /* Index 1 = parameter types */291dh_key_types, /* Index 2 = key types */292dh_all_types /* Index 3 = 1 + 2 */293};294295static const OSSL_PARAM *dh_imexport_types(int selection)296{297int type_select = 0;298299if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)300type_select += 1;301if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)302type_select += 2;303return dh_types[type_select];304}305306static const OSSL_PARAM *dh_import_types(int selection)307{308return dh_imexport_types(selection);309}310311static const OSSL_PARAM *dh_export_types(int selection)312{313return dh_imexport_types(selection);314}315316static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])317{318DH *dh = key;319OSSL_PARAM *p;320321if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL322&& !OSSL_PARAM_set_int(p, DH_bits(dh)))323return 0;324if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL325&& !OSSL_PARAM_set_int(p, DH_security_bits(dh)))326return 0;327if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL328&& !OSSL_PARAM_set_int(p, DH_size(dh)))329return 0;330if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {331if (p->data_type != OSSL_PARAM_OCTET_STRING)332return 0;333p->return_size = ossl_dh_key2buf(dh, (unsigned char **)&p->data,334p->data_size, 0);335if (p->return_size == 0)336return 0;337}338339return ossl_dh_params_todata(dh, NULL, params)340&& ossl_dh_key_todata(dh, NULL, params, 1);341}342343static const OSSL_PARAM dh_params[] = {344OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),345OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),346OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),347OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),348DH_IMEXPORTABLE_PARAMETERS,349DH_IMEXPORTABLE_PUBLIC_KEY,350DH_IMEXPORTABLE_PRIVATE_KEY,351OSSL_PARAM_END352};353354static const OSSL_PARAM *dh_gettable_params(void *provctx)355{356return dh_params;357}358359static const OSSL_PARAM dh_known_settable_params[] = {360OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),361OSSL_PARAM_END362};363364static const OSSL_PARAM *dh_settable_params(void *provctx)365{366return dh_known_settable_params;367}368369static int dh_set_params(void *key, const OSSL_PARAM params[])370{371DH *dh = key;372const OSSL_PARAM *p;373374p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);375if (p != NULL376&& (p->data_type != OSSL_PARAM_OCTET_STRING377|| !ossl_dh_buf2key(dh, p->data, p->data_size)))378return 0;379380return 1;381}382383static int dh_validate_public(const DH *dh, int checktype)384{385const BIGNUM *pub_key = NULL;386int res = 0;387388DH_get0_key(dh, &pub_key, NULL);389if (pub_key == NULL)390return 0;391392/*393* The partial test is only valid for named group's with q = (p - 1) / 2394* but for that case it is also fully sufficient to check the key validity.395*/396if (ossl_dh_is_named_safe_prime_group(dh))397return ossl_dh_check_pub_key_partial(dh, pub_key, &res);398399return DH_check_pub_key_ex(dh, pub_key);400}401402static int dh_validate_private(const DH *dh)403{404int status = 0;405const BIGNUM *priv_key = NULL;406407DH_get0_key(dh, NULL, &priv_key);408if (priv_key == NULL)409return 0;410return ossl_dh_check_priv_key(dh, priv_key, &status);411}412413static int dh_validate(const void *keydata, int selection, int checktype)414{415const DH *dh = keydata;416int ok = 1;417418if (!ossl_prov_is_running())419return 0;420421if ((selection & DH_POSSIBLE_SELECTIONS) == 0)422return 1; /* nothing to validate */423424if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {425/*426* Both of these functions check parameters. DH_check_params_ex()427* performs a lightweight check (e.g. it does not check that p is a428* safe prime)429*/430if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)431ok = ok && DH_check_params_ex(dh);432else433ok = ok && DH_check_ex(dh);434}435436if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)437ok = ok && dh_validate_public(dh, checktype);438439if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)440ok = ok && dh_validate_private(dh);441442if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)443== OSSL_KEYMGMT_SELECT_KEYPAIR)444ok = ok && ossl_dh_check_pairwise(dh, 0);445return ok;446}447448static void *dh_gen_init_base(void *provctx, int selection,449const OSSL_PARAM params[], int type)450{451OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);452struct dh_gen_ctx *gctx = NULL;453454if (!ossl_prov_is_running())455return NULL;456457if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR458| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)459return NULL;460461if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {462gctx->selection = selection;463gctx->libctx = libctx;464gctx->pbits = 2048;465gctx->qbits = 224;466gctx->mdname = NULL;467#ifdef FIPS_MODULE468gctx->gen_type = (type == DH_FLAG_TYPE_DHX)469? DH_PARAMGEN_TYPE_FIPS_186_4470: DH_PARAMGEN_TYPE_GROUP;471#else472gctx->gen_type = (type == DH_FLAG_TYPE_DHX)473? DH_PARAMGEN_TYPE_FIPS_186_2474: DH_PARAMGEN_TYPE_GENERATOR;475#endif476gctx->gindex = -1;477gctx->hindex = 0;478gctx->pcounter = -1;479gctx->generator = DH_GENERATOR_2;480gctx->dh_type = type;481}482if (!dh_gen_set_params(gctx, params)) {483OPENSSL_free(gctx);484gctx = NULL;485}486return gctx;487}488489static void *dh_gen_init(void *provctx, int selection,490const OSSL_PARAM params[])491{492return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DH);493}494495static void *dhx_gen_init(void *provctx, int selection,496const OSSL_PARAM params[])497{498return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DHX);499}500501static int dh_gen_set_template(void *genctx, void *templ)502{503struct dh_gen_ctx *gctx = genctx;504DH *dh = templ;505506if (!ossl_prov_is_running() || gctx == NULL || dh == NULL)507return 0;508gctx->ffc_params = ossl_dh_get0_params(dh);509return 1;510}511512static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed,513size_t seedlen)514{515OPENSSL_clear_free(gctx->seed, gctx->seedlen);516gctx->seed = NULL;517gctx->seedlen = 0;518if (seed != NULL && seedlen > 0) {519gctx->seed = OPENSSL_memdup(seed, seedlen);520if (gctx->seed == NULL)521return 0;522gctx->seedlen = seedlen;523}524return 1;525}526527static int dh_gen_common_set_params(void *genctx, const OSSL_PARAM params[])528{529struct dh_gen_ctx *gctx = genctx;530const OSSL_PARAM *p;531int gen_type = -1;532533if (gctx == NULL)534return 0;535if (ossl_param_is_empty(params))536return 1;537538p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);539if (p != NULL) {540if (p->data_type != OSSL_PARAM_UTF8_STRING541|| ((gen_type =542dh_gen_type_name2id_w_default(p->data, gctx->dh_type)) == -1)) {543ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);544return 0;545}546if (gen_type != -1)547gctx->gen_type = gen_type;548}549p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);550if (p != NULL) {551const DH_NAMED_GROUP *group = NULL;552553if (p->data_type != OSSL_PARAM_UTF8_STRING554|| p->data == NULL555|| (group = ossl_ffc_name_to_dh_named_group(p->data)) == NULL556|| ((gctx->group_nid =557ossl_ffc_named_group_get_uid(group)) == NID_undef)) {558ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);559return 0;560}561}562if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL563&& !OSSL_PARAM_get_size_t(p, &gctx->pbits))564return 0;565p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);566if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len))567return 0;568return 1;569}570571static const OSSL_PARAM *dh_gen_settable_params(ossl_unused void *genctx,572ossl_unused void *provctx)573{574static const OSSL_PARAM dh_gen_settable[] = {575OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),576OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),577OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),578OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),579OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_GENERATOR, NULL),580OSSL_PARAM_END581};582return dh_gen_settable;583}584585static const OSSL_PARAM *dhx_gen_settable_params(ossl_unused void *genctx,586ossl_unused void *provctx)587{588static const OSSL_PARAM dhx_gen_settable[] = {589OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),590OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),591OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),592OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),593OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),594OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),595OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),596OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),597OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),598OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),599OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),600OSSL_PARAM_END601};602return dhx_gen_settable;603}604605static int dhx_gen_set_params(void *genctx, const OSSL_PARAM params[])606{607struct dh_gen_ctx *gctx = genctx;608const OSSL_PARAM *p;609610if (!dh_gen_common_set_params(genctx, params))611return 0;612613/* Parameters related to fips186-4 and fips186-2 */614p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);615if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex))616return 0;617p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);618if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter))619return 0;620p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);621if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex))622return 0;623p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);624if (p != NULL625&& (p->data_type != OSSL_PARAM_OCTET_STRING626|| !dh_set_gen_seed(gctx, p->data, p->data_size)))627return 0;628if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL629&& !OSSL_PARAM_get_size_t(p, &gctx->qbits))630return 0;631p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);632if (p != NULL) {633if (p->data_type != OSSL_PARAM_UTF8_STRING)634return 0;635OPENSSL_free(gctx->mdname);636gctx->mdname = OPENSSL_strdup(p->data);637if (gctx->mdname == NULL)638return 0;639}640p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);641if (p != NULL) {642if (p->data_type != OSSL_PARAM_UTF8_STRING)643return 0;644OPENSSL_free(gctx->mdprops);645gctx->mdprops = OPENSSL_strdup(p->data);646if (gctx->mdprops == NULL)647return 0;648}649650/* Parameters that are not allowed for DHX */651p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);652if (p != NULL) {653ERR_raise(ERR_LIB_PROV, ERR_R_UNSUPPORTED);654return 0;655}656return 1;657}658659static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[])660{661struct dh_gen_ctx *gctx = genctx;662const OSSL_PARAM *p;663664if (!dh_gen_common_set_params(genctx, params))665return 0;666667p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);668if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator))669return 0;670671/* Parameters that are not allowed for DH */672if (OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX) != NULL673|| OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER) != NULL674|| OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H) != NULL675|| OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED) != NULL676|| OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS) != NULL677|| OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST) != NULL678|| OSSL_PARAM_locate_const(params,679OSSL_PKEY_PARAM_FFC_DIGEST_PROPS) != NULL) {680ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);681return 0;682}683return 1;684}685686static int dh_gencb(int p, int n, BN_GENCB *cb)687{688struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);689OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };690691params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);692params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);693694return gctx->cb(params, gctx->cbarg);695}696697static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)698{699int ret = 0;700struct dh_gen_ctx *gctx = genctx;701DH *dh = NULL;702BN_GENCB *gencb = NULL;703FFC_PARAMS *ffc;704705if (!ossl_prov_is_running() || gctx == NULL)706return NULL;707708/*709* If a group name is selected then the type is group regardless of what710* the user selected. This overrides rather than errors for backwards711* compatibility.712*/713if (gctx->group_nid != NID_undef)714gctx->gen_type = DH_PARAMGEN_TYPE_GROUP;715716/*717* Do a bounds check on context gen_type. Must be in range:718* DH_PARAMGEN_TYPE_GENERATOR <= gen_type <= DH_PARAMGEN_TYPE_GROUP719* Noted here as this needs to be adjusted if a new group type is720* added.721*/722if (!ossl_assert((gctx->gen_type >= DH_PARAMGEN_TYPE_GENERATOR)723&& (gctx->gen_type <= DH_PARAMGEN_TYPE_GROUP))) {724ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,725"gen_type set to unsupported value %d", gctx->gen_type);726return NULL;727}728729/* For parameter generation - If there is a group name just create it */730if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP731&& gctx->ffc_params == NULL) {732/* Select a named group if there is not one already */733if (gctx->group_nid == NID_undef)734gctx->group_nid = ossl_dh_get_named_group_uid_from_size(gctx->pbits);735if (gctx->group_nid == NID_undef)736return NULL;737dh = ossl_dh_new_by_nid_ex(gctx->libctx, gctx->group_nid);738if (dh == NULL)739return NULL;740ffc = ossl_dh_get0_params(dh);741} else {742dh = ossl_dh_new_ex(gctx->libctx);743if (dh == NULL)744return NULL;745ffc = ossl_dh_get0_params(dh);746747/* Copy the template value if one was passed */748if (gctx->ffc_params != NULL749&& !ossl_ffc_params_copy(ffc, gctx->ffc_params))750goto end;751752if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))753goto end;754if (gctx->gindex != -1) {755ossl_ffc_params_set_gindex(ffc, gctx->gindex);756if (gctx->pcounter != -1)757ossl_ffc_params_set_pcounter(ffc, gctx->pcounter);758} else if (gctx->hindex != 0) {759ossl_ffc_params_set_h(ffc, gctx->hindex);760}761if (gctx->mdname != NULL)762ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops);763gctx->cb = osslcb;764gctx->cbarg = cbarg;765gencb = BN_GENCB_new();766if (gencb != NULL)767BN_GENCB_set(gencb, dh_gencb, genctx);768769if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {770/*771* NOTE: The old safe prime generator code is not used in fips mode,772* (i.e internally it ignores the generator and chooses a named773* group based on pbits.774*/775if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR)776ret = DH_generate_parameters_ex(dh, gctx->pbits,777gctx->generator, gencb);778else779ret = ossl_dh_generate_ffc_parameters(dh, gctx->gen_type,780gctx->pbits, gctx->qbits,781gencb);782if (ret <= 0)783goto end;784}785}786787if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {788if (ffc->p == NULL || ffc->g == NULL)789goto end;790if (gctx->priv_len > 0)791DH_set_length(dh, (long)gctx->priv_len);792ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,793gctx->gen_type == DH_PARAMGEN_TYPE_FIPS_186_2);794if (DH_generate_key(dh) <= 0)795goto end;796#ifdef FIPS_MODULE797if (!ossl_fips_self_testing()) {798ret = ossl_dh_check_pairwise(dh, 0);799if (ret <= 0) {800ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);801goto end;802}803}804#endif /* FIPS_MODULE */805}806DH_clear_flags(dh, DH_FLAG_TYPE_MASK);807DH_set_flags(dh, gctx->dh_type);808809ret = 1;810end:811if (ret <= 0) {812DH_free(dh);813dh = NULL;814}815BN_GENCB_free(gencb);816return dh;817}818819static void dh_gen_cleanup(void *genctx)820{821struct dh_gen_ctx *gctx = genctx;822823if (gctx == NULL)824return;825826OPENSSL_free(gctx->mdname);827OPENSSL_free(gctx->mdprops);828OPENSSL_clear_free(gctx->seed, gctx->seedlen);829OPENSSL_free(gctx);830}831832static void *dh_load(const void *reference, size_t reference_sz)833{834DH *dh = NULL;835836if (ossl_prov_is_running() && reference_sz == sizeof(dh)) {837/* The contents of the reference is the address to our object */838dh = *(DH **)reference;839/* We grabbed, so we detach it */840*(DH **)reference = NULL;841return dh;842}843return NULL;844}845846static void *dh_dup(const void *keydata_from, int selection)847{848if (ossl_prov_is_running())849return ossl_dh_dup(keydata_from, selection);850return NULL;851}852853const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = {854{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },855{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },856{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },857{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params },858{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,859(void (*)(void))dh_gen_settable_params },860{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },861{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },862{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },863{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },864{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },865{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },866{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },867{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },868{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },869{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },870{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },871{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },872{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },873{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },874{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },875{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },876OSSL_DISPATCH_END877};878879/* For any DH key, we use the "DH" algorithms regardless of sub-type. */880static const char *dhx_query_operation_name(int operation_id)881{882return "DH";883}884885const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = {886{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dhx_newdata },887{ OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dhx_gen_init },888{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },889{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dhx_gen_set_params },890{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,891(void (*)(void))dhx_gen_settable_params },892{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },893{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },894{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },895{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },896{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },897{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },898{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },899{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },900{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },901{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },902{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },903{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },904{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },905{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },906{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },907{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,908(void (*)(void))dhx_query_operation_name },909{ OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },910OSSL_DISPATCH_END911};912913914