Update core_names.h fields and document most fields.
[openssl.git] / providers / implementations / keymgmt / dh_kmgmt.c
1 /*
2  * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /*
11  * DH low level APIs are deprecated for public use, but still ok for
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15
16 #include <string.h> /* strcmp */
17 #include <openssl/core_numbers.h>
18 #include <openssl/core_names.h>
19 #include <openssl/bn.h>
20 #include <openssl/err.h>
21 #include "prov/implementations.h"
22 #include "prov/providercommon.h"
23 #include "prov/provider_ctx.h"
24 #include "crypto/dh.h"
25 #include "internal/sizes.h"
26 #include "internal/nelem.h"
27 #include "internal/param_build_set.h"
28
29 static OSSL_OP_keymgmt_new_fn dh_newdata;
30 static OSSL_OP_keymgmt_free_fn dh_freedata;
31 static OSSL_OP_keymgmt_gen_init_fn dh_gen_init;
32 static OSSL_OP_keymgmt_gen_set_template_fn dh_gen_set_template;
33 static OSSL_OP_keymgmt_gen_set_params_fn dh_gen_set_params;
34 static OSSL_OP_keymgmt_gen_settable_params_fn dh_gen_settable_params;
35 static OSSL_OP_keymgmt_gen_fn dh_gen;
36 static OSSL_OP_keymgmt_gen_cleanup_fn dh_gen_cleanup;
37 static OSSL_OP_keymgmt_get_params_fn dh_get_params;
38 static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params;
39 static OSSL_OP_keymgmt_has_fn dh_has;
40 static OSSL_OP_keymgmt_match_fn dh_match;
41 static OSSL_OP_keymgmt_validate_fn dh_validate;
42 static OSSL_OP_keymgmt_import_fn dh_import;
43 static OSSL_OP_keymgmt_import_types_fn dh_import_types;
44 static OSSL_OP_keymgmt_export_fn dh_export;
45 static OSSL_OP_keymgmt_export_types_fn dh_export_types;
46
47 #define DH_POSSIBLE_SELECTIONS                                                 \
48     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
49
50 struct dh_gen_ctx {
51     OPENSSL_CTX *libctx;
52
53     FFC_PARAMS *ffc_params;
54     int selection;
55     /* All these parameters are used for parameter generation only */
56     /* If there is a group name then the remaining parameters are not needed */
57     int group_nid;
58     size_t pbits;
59     size_t qbits;
60     EVP_MD *md;
61     unsigned char *seed; /* optional FIPS186-4 param for testing */
62     size_t seedlen;
63     int gindex; /* optional  FIPS186-4 generator index (ignored if -1) */
64     int gen_type; /* see dhtype2id */
65     int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */
66     int pcounter;
67     int hindex;
68     int priv_len;
69
70     OSSL_CALLBACK *cb;
71     void *cbarg;
72 };
73
74 typedef struct dh_name2id_st{
75     const char *name;
76     int id;
77 } DH_GENTYPE_NAME2ID;
78
79 static const DH_GENTYPE_NAME2ID dhtype2id[]=
80 {
81     { "default", DH_PARAMGEN_TYPE_FIPS_186_4 },
82     { "fips186_4", DH_PARAMGEN_TYPE_FIPS_186_4 },
83     { "fips186_2", DH_PARAMGEN_TYPE_FIPS_186_2 },
84     { "group", DH_PARAMGEN_TYPE_GROUP },
85     { "generator", DH_PARAMGEN_TYPE_GENERATOR }
86 };
87
88 const char *dh_gen_type_id2name(int id)
89 {
90     size_t i;
91
92     for (i = 0; i < OSSL_NELEM(dhtype2id); ++i) {
93         if (dhtype2id[i].id == id)
94             return dhtype2id[i].name;
95     }
96     return NULL;
97 }
98
99 static int dh_gen_type_name2id(const char *name)
100 {
101     size_t i;
102
103     for (i = 0; i < OSSL_NELEM(dhtype2id); ++i) {
104         if (strcmp(dhtype2id[i].name, name) == 0)
105             return dhtype2id[i].id;
106     }
107     return -1;
108 }
109
110 static int dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
111 {
112     const BIGNUM *priv = NULL, *pub = NULL;
113
114     if (dh == NULL)
115         return 0;
116
117     DH_get0_key(dh, &pub, &priv);
118     if (priv != NULL
119         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv))
120         return 0;
121     if (pub != NULL
122         && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub))
123         return 0;
124
125     return 1;
126 }
127
128 static void *dh_newdata(void *provctx)
129 {
130     return dh_new_with_libctx(PROV_LIBRARY_CONTEXT_OF(provctx));
131 }
132
133 static void dh_freedata(void *keydata)
134 {
135     DH_free(keydata);
136 }
137
138 static int dh_has(void *keydata, int selection)
139 {
140     DH *dh = keydata;
141     int ok = 0;
142
143     if (dh != NULL) {
144         if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
145             ok = 1;
146
147         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
148             ok = ok && (DH_get0_pub_key(dh) != NULL);
149         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
150             ok = ok && (DH_get0_priv_key(dh) != NULL);
151         if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
152             ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
153     }
154     return ok;
155 }
156
157 static int dh_match(const void *keydata1, const void *keydata2, int selection)
158 {
159     const DH *dh1 = keydata1;
160     const DH *dh2 = keydata2;
161     int ok = 1;
162
163     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
164         ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0;
165     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
166         ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0;
167     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
168         FFC_PARAMS *dhparams1 = dh_get0_params((DH *)dh1);
169         FFC_PARAMS *dhparams2 = dh_get0_params((DH *)dh2);
170
171         ok = ok && ffc_params_cmp(dhparams1, dhparams2, 1);
172     }
173     return ok;
174 }
175
176 static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
177 {
178     DH *dh = keydata;
179     int ok = 1;
180
181     if (dh == NULL)
182         return 0;
183
184     if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
185         return 0;
186
187     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
188         ok = ok && dh_ffc_params_fromdata(dh, params);
189
190     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
191         ok = ok && dh_key_fromdata(dh, params);
192
193     return ok;
194 }
195
196 static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
197                      void *cbarg)
198 {
199     DH *dh = keydata;
200     OSSL_PARAM_BLD *tmpl = NULL;
201     OSSL_PARAM *params = NULL;
202     int ok = 1;
203
204     if (dh == NULL)
205         return 0;
206
207     tmpl = OSSL_PARAM_BLD_new();
208     if (tmpl == NULL)
209         return 0;
210
211     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
212         ok = ok && ffc_params_todata(dh_get0_params(dh), tmpl, NULL);
213     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
214         ok = ok && dh_key_todata(dh, tmpl, NULL);
215
216     if (!ok
217         || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
218         ok = 0;
219         goto err;
220     }
221     ok = param_cb(params, cbarg);
222     OSSL_PARAM_BLD_free_params(params);
223 err:
224     OSSL_PARAM_BLD_free(tmpl);
225     return ok;
226 }
227
228 /* IMEXPORT = IMPORT + EXPORT */
229
230 # define DH_IMEXPORTABLE_PARAMETERS                                            \
231     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0),                             \
232     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0),                             \
233     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0),                             \
234     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0),                      \
235     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),                          \
236     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),                        \
237     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),                               \
238     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),                \
239     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DH_GROUP, NULL, 0)
240 # define DH_IMEXPORTABLE_PUBLIC_KEY                                            \
241     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
242 # define DH_IMEXPORTABLE_PRIVATE_KEY                                           \
243     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
244 static const OSSL_PARAM dh_all_types[] = {
245     DH_IMEXPORTABLE_PARAMETERS,
246     DH_IMEXPORTABLE_PUBLIC_KEY,
247     DH_IMEXPORTABLE_PRIVATE_KEY,
248     OSSL_PARAM_END
249 };
250 static const OSSL_PARAM dh_parameter_types[] = {
251     DH_IMEXPORTABLE_PARAMETERS,
252     OSSL_PARAM_END
253 };
254 static const OSSL_PARAM dh_key_types[] = {
255     DH_IMEXPORTABLE_PUBLIC_KEY,
256     DH_IMEXPORTABLE_PRIVATE_KEY,
257     OSSL_PARAM_END
258 };
259 static const OSSL_PARAM *dh_types[] = {
260     NULL,                        /* Index 0 = none of them */
261     dh_parameter_types,          /* Index 1 = parameter types */
262     dh_key_types,                /* Index 2 = key types */
263     dh_all_types                 /* Index 3 = 1 + 2 */
264 };
265
266 static const OSSL_PARAM *dh_imexport_types(int selection)
267 {
268     int type_select = 0;
269
270     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
271         type_select += 1;
272     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
273         type_select += 2;
274     return dh_types[type_select];
275 }
276
277 static const OSSL_PARAM *dh_import_types(int selection)
278 {
279     return dh_imexport_types(selection);
280 }
281
282 static const OSSL_PARAM *dh_export_types(int selection)
283 {
284     return dh_imexport_types(selection);
285 }
286
287 static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])
288 {
289     DH *dh = key;
290     OSSL_PARAM *p;
291
292     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
293         && !OSSL_PARAM_set_int(p, DH_bits(dh)))
294         return 0;
295     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
296         && !OSSL_PARAM_set_int(p, DH_security_bits(dh)))
297         return 0;
298     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
299         && !OSSL_PARAM_set_int(p, DH_size(dh)))
300         return 0;
301     return ffc_params_todata(dh_get0_params(dh), NULL, params)
302            && dh_key_todata(dh, NULL, params);
303 }
304
305 static const OSSL_PARAM dh_params[] = {
306     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
307     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
308     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
309     DH_IMEXPORTABLE_PARAMETERS,
310     DH_IMEXPORTABLE_PUBLIC_KEY,
311     DH_IMEXPORTABLE_PRIVATE_KEY,
312     OSSL_PARAM_END
313 };
314
315 static const OSSL_PARAM *dh_gettable_params(void)
316 {
317     return dh_params;
318 }
319
320 static int dh_validate_public(DH *dh)
321 {
322     const BIGNUM *pub_key = NULL;
323
324     DH_get0_key(dh, &pub_key, NULL);
325     if (pub_key == NULL)
326         return 0;
327     return DH_check_pub_key_ex(dh, pub_key);
328 }
329
330 static int dh_validate_private(DH *dh)
331 {
332     int status = 0;
333     const BIGNUM *priv_key = NULL;
334
335     DH_get0_key(dh, NULL, &priv_key);
336     if (priv_key == NULL)
337         return 0;
338     return dh_check_priv_key(dh, priv_key, &status);;
339 }
340
341 static int dh_validate(void *keydata, int selection)
342 {
343     DH *dh = keydata;
344     int ok = 0;
345
346     if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
347         ok = 1;
348
349     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
350         ok = ok && DH_check_params_ex(dh);
351
352     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
353         ok = ok && dh_validate_public(dh);
354
355     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
356         ok = ok && dh_validate_private(dh);
357
358     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
359             == OSSL_KEYMGMT_SELECT_KEYPAIR)
360         ok = ok && dh_check_pairwise(dh);
361     return ok;
362 }
363
364 static void *dh_gen_init(void *provctx, int selection)
365 {
366     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
367     struct dh_gen_ctx *gctx = NULL;
368
369     if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
370                       | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)
371         return NULL;
372
373     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
374         gctx->selection = selection;
375         gctx->libctx = libctx;
376         gctx->pbits = 2048;
377         gctx->qbits = 224;
378         gctx->md = NULL;
379         gctx->gen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
380         gctx->gindex = -1;
381         gctx->hindex = 0;
382         gctx->pcounter = -1;
383         gctx->generator = DH_GENERATOR_2;
384     }
385     return gctx;
386 }
387
388 static int dh_gen_set_template(void *genctx, void *templ)
389 {
390     struct dh_gen_ctx *gctx = genctx;
391     DH *dh = templ;
392
393     if (gctx == NULL || dh == NULL)
394         return 0;
395     gctx->ffc_params = dh_get0_params(dh);
396     return 1;
397 }
398
399 static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed,
400                            size_t seedlen)
401 {
402     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
403     gctx->seed = NULL;
404     gctx->seedlen = 0;
405     if (seed != NULL && seedlen > 0) {
406         gctx->seed = OPENSSL_memdup(seed, seedlen);
407         if (gctx->seed == NULL)
408             return 0;
409         gctx->seedlen = seedlen;
410     }
411     return 1;
412 }
413
414 static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[])
415 {
416     struct dh_gen_ctx *gctx = genctx;
417     const OSSL_PARAM *p;
418
419     if (gctx == NULL)
420         return 0;
421
422     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
423     if (p != NULL) {
424         if (p->data_type != OSSL_PARAM_UTF8_STRING
425             || ((gctx->gen_type = dh_gen_type_name2id(p->data)) == -1)) {
426             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
427             return 0;
428         }
429     }
430     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GROUP);
431     if (p != NULL) {
432         if (p->data_type != OSSL_PARAM_UTF8_STRING
433            || ((gctx->group_nid = ffc_named_group_to_uid(p->data)) == NID_undef)) {
434             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
435             return 0;
436         }
437         gctx->gen_type = DH_PARAMGEN_TYPE_GROUP;
438     }
439     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);
440     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator))
441         return 0;
442     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
443     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex))
444         return 0;
445     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
446     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter))
447         return 0;
448     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
449     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex))
450         return 0;
451     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
452     if (p != NULL
453         && (p->data_type != OSSL_PARAM_OCTET_STRING
454             || !dh_set_gen_seed(gctx, p->data, p->data_size)))
455             return 0;
456
457     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
458         && !OSSL_PARAM_get_size_t(p, &gctx->pbits))
459         return 0;
460     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
461         && !OSSL_PARAM_get_size_t(p, &gctx->qbits))
462         return 0;
463     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
464     if (p != NULL) {
465         const OSSL_PARAM *p1;
466         char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' };
467         char *str = mdprops;
468
469         if (p->data_type != OSSL_PARAM_UTF8_STRING)
470             return 0;
471         p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
472         if (p1 != NULL
473             && !OSSL_PARAM_get_utf8_string(p1, &str, sizeof(mdprops)))
474             return 0;
475         EVP_MD_free(gctx->md);
476         gctx->md = EVP_MD_fetch(gctx->libctx, p->data, mdprops);
477         if (gctx->md == NULL)
478             return 0;
479     }
480     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
481     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len))
482         return 0;
483     return 1;
484 }
485
486 static const OSSL_PARAM *dh_gen_settable_params(void *provctx)
487 {
488     static OSSL_PARAM settable[] = {
489         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DH_GROUP, NULL, 0),
490         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
491         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_GENERATOR, NULL),
492         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
493         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
494         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
495         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
496         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
497         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
498         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
499         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
500         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
501         OSSL_PARAM_END
502     };
503     return settable;
504 }
505
506 static int dh_gencb(int p, int n, BN_GENCB *cb)
507 {
508     struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);
509     OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
510
511     params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
512     params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
513
514     return gctx->cb(params, gctx->cbarg);
515 }
516
517 static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
518 {
519     int ret = 0;
520     struct dh_gen_ctx *gctx = genctx;
521     DH *dh = NULL;
522     BN_GENCB *gencb = NULL;
523     FFC_PARAMS *ffc;
524
525     if (gctx == NULL)
526         return NULL;
527
528     /* For parameter generation - If there is a group name just create it */
529     if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP) {
530         /* Select a named group if there is not one already */
531         if (gctx->group_nid == NID_undef)
532             gctx->group_nid = dh_get_named_group_uid_from_size(gctx->pbits);
533         if (gctx->group_nid == NID_undef)
534             return NULL;
535         dh = dh_new_by_nid_with_libctx(gctx->libctx, gctx->group_nid);
536         if (dh == NULL)
537             return NULL;
538         ffc = dh_get0_params(dh);
539     } else {
540         dh = dh_new_with_libctx(gctx->libctx);
541         if (dh == NULL)
542             return NULL;
543         ffc = dh_get0_params(dh);
544
545         /* Copy the template value if one was passed */
546         if (gctx->ffc_params != NULL
547             && !ffc_params_copy(ffc, gctx->ffc_params))
548             goto end;
549
550         if (!ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
551             goto end;
552         if (gctx->gindex != -1) {
553             ffc_params_set_gindex(ffc, gctx->gindex);
554             if (gctx->pcounter != -1)
555                 ffc_params_set_pcounter(ffc, gctx->pcounter);
556         } else if (gctx->hindex != 0) {
557             ffc_params_set_h(ffc, gctx->hindex);
558         }
559         gctx->cb = osslcb;
560         gctx->cbarg = cbarg;
561         gencb = BN_GENCB_new();
562         if (gencb != NULL)
563             BN_GENCB_set(gencb, dh_gencb, genctx);
564
565         if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
566             /*
567              * NOTE: The old safe prime generator code is not used in fips mode,
568              * (i.e internally it ignores the generator and chooses a named
569              * group based on pbits.
570              */
571             if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR)
572                 ret = DH_generate_parameters_ex(dh, gctx->pbits,
573                                                 gctx->generator, gencb);
574             else
575                 ret = dh_generate_ffc_parameters(dh, gctx->gen_type, gctx->pbits,
576                                                  gctx->qbits, gctx->md, gencb);
577             if (ret <= 0)
578                 goto end;
579         }
580     }
581
582     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
583         if (ffc->p == NULL || ffc->g == NULL)
584             goto end;
585         if (gctx->priv_len > 0)
586             DH_set_length(dh, (long)gctx->priv_len);
587         if (DH_generate_key(dh) <= 0)
588             goto end;
589     }
590     ret = 1;
591 end:
592     if (ret <= 0) {
593         DH_free(dh);
594         dh = NULL;
595     }
596     BN_GENCB_free(gencb);
597     return dh;
598 }
599
600 static void dh_gen_cleanup(void *genctx)
601 {
602     struct dh_gen_ctx *gctx = genctx;
603
604     if (gctx == NULL)
605         return;
606
607     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
608     EVP_MD_free(gctx->md);
609     OPENSSL_free(gctx);
610 }
611
612 const OSSL_DISPATCH dh_keymgmt_functions[] = {
613     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
614     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
615     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
616     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params },
617     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
618       (void (*)(void))dh_gen_settable_params },
619     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
620     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
621     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
622     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
623     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
624     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
625     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
626     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
627     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
628     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
629     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
630     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
631     { 0, NULL }
632 };