Fix DH_get_nid() so that it does not cache values.
[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_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP, NULL, 0),                \
239     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, 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     return DH_check_pub_key_ex(dh, pub_key);
326 }
327
328 static int dh_validate_private(DH *dh)
329 {
330     int status = 0;
331     const BIGNUM *priv_key = NULL;
332
333     DH_get0_key(dh, NULL, &priv_key);
334     return dh_check_priv_key(dh, priv_key, &status);;
335 }
336
337 static int dh_validate(void *keydata, int selection)
338 {
339     DH *dh = keydata;
340     int ok = 0;
341
342     if ((selection & DH_POSSIBLE_SELECTIONS) != 0)
343         ok = 1;
344
345     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
346         ok = ok && DH_check_params_ex(dh);
347
348     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
349         ok = ok && dh_validate_public(dh);
350
351     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
352         ok = ok && dh_validate_private(dh);
353
354     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
355             == OSSL_KEYMGMT_SELECT_KEYPAIR)
356         ok = ok && dh_check_pairwise(dh);
357     return ok;
358 }
359
360 static void *dh_gen_init(void *provctx, int selection)
361 {
362     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
363     struct dh_gen_ctx *gctx = NULL;
364
365     if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
366                       | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)
367         return NULL;
368
369     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
370         gctx->selection = selection;
371         gctx->libctx = libctx;
372         gctx->pbits = 2048;
373         gctx->qbits = 224;
374         gctx->md = NULL;
375         gctx->gen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
376         gctx->gindex = -1;
377         gctx->hindex = 0;
378         gctx->pcounter = -1;
379         gctx->generator = DH_GENERATOR_2;
380     }
381     return gctx;
382 }
383
384 static int dh_gen_set_template(void *genctx, void *templ)
385 {
386     struct dh_gen_ctx *gctx = genctx;
387     DH *dh = templ;
388
389     if (gctx == NULL || dh == NULL)
390         return 0;
391     gctx->ffc_params = dh_get0_params(dh);
392     return 1;
393 }
394
395 static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed,
396                            size_t seedlen)
397 {
398     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
399     gctx->seed = NULL;
400     gctx->seedlen = 0;
401     if (seed != NULL && seedlen > 0) {
402         gctx->seed = OPENSSL_memdup(seed, seedlen);
403         if (gctx->seed == NULL)
404             return 0;
405         gctx->seedlen = seedlen;
406     }
407     return 1;
408 }
409
410 static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[])
411 {
412     struct dh_gen_ctx *gctx = genctx;
413     const OSSL_PARAM *p;
414
415     if (gctx == NULL)
416         return 0;
417
418     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
419     if (p != NULL) {
420         if (p->data_type != OSSL_PARAM_UTF8_STRING
421             || ((gctx->gen_type = dh_gen_type_name2id(p->data)) == -1)) {
422             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
423             return 0;
424         }
425     }
426     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GROUP);
427     if (p != NULL) {
428         if (p->data_type != OSSL_PARAM_UTF8_STRING
429            || ((gctx->group_nid = ffc_named_group_to_uid(p->data)) == NID_undef)) {
430             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
431             return 0;
432         }
433         gctx->gen_type = DH_PARAMGEN_TYPE_GROUP;
434     }
435     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GENERATOR);
436     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator))
437         return 0;
438     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
439     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex))
440         return 0;
441     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
442     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter))
443         return 0;
444     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
445     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex))
446         return 0;
447     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
448     if (p != NULL
449         && (p->data_type != OSSL_PARAM_OCTET_STRING
450             || !dh_set_gen_seed(gctx, p->data, p->data_size)))
451             return 0;
452
453     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
454         && !OSSL_PARAM_get_size_t(p, &gctx->pbits))
455         return 0;
456     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
457         && !OSSL_PARAM_get_size_t(p, &gctx->qbits))
458         return 0;
459     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
460     if (p != NULL) {
461         const OSSL_PARAM *p1;
462         char mdprops[OSSL_MAX_PROPQUERY_SIZE] = { '\0' };
463         char *str = mdprops;
464
465         if (p->data_type != OSSL_PARAM_UTF8_STRING)
466             return 0;
467         p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
468         if (p1 != NULL
469             && !OSSL_PARAM_get_utf8_string(p1, &str, sizeof(mdprops)))
470             return 0;
471         EVP_MD_free(gctx->md);
472         gctx->md = EVP_MD_fetch(gctx->libctx, p->data, mdprops);
473         if (gctx->md == NULL)
474             return 0;
475     }
476     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
477     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len))
478         return 0;
479     return 1;
480 }
481
482 static const OSSL_PARAM *dh_gen_settable_params(void *provctx)
483 {
484     static OSSL_PARAM settable[] = {
485         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP, NULL, 0),
486         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
487         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
488         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
489         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
490         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
491         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
492         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
493         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GENERATOR, NULL),
494         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
495         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
496         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
497         OSSL_PARAM_END
498     };
499     return settable;
500 }
501
502 static int dh_gencb(int p, int n, BN_GENCB *cb)
503 {
504     struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);
505     OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
506
507     params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
508     params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
509
510     return gctx->cb(params, gctx->cbarg);
511 }
512
513 static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
514 {
515     int ret = 0;
516     struct dh_gen_ctx *gctx = genctx;
517     DH *dh = NULL;
518     BN_GENCB *gencb = NULL;
519     FFC_PARAMS *ffc;
520
521     if (gctx == NULL)
522         return NULL;
523
524     /* For parameter generation - If there is a group name just create it */
525     if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP) {
526         /* Select a named group if there is not one already */
527         if (gctx->group_nid == NID_undef)
528             gctx->group_nid = dh_get_named_group_uid_from_size(gctx->pbits);
529         if (gctx->group_nid == NID_undef)
530             return NULL;
531         dh = dh_new_by_nid_with_libctx(gctx->libctx, gctx->group_nid);
532         if (dh == NULL)
533             return NULL;
534         ffc = dh_get0_params(dh);
535     } else {
536         dh = dh_new_with_libctx(gctx->libctx);
537         if (dh == NULL)
538             return NULL;
539         ffc = dh_get0_params(dh);
540
541         /* Copy the template value if one was passed */
542         if (gctx->ffc_params != NULL
543             && !ffc_params_copy(ffc, gctx->ffc_params))
544             goto end;
545
546         if (!ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
547             goto end;
548         if (gctx->gindex != -1) {
549             ffc_params_set_gindex(ffc, gctx->gindex);
550             if (gctx->pcounter != -1)
551                 ffc_params_set_pcounter(ffc, gctx->pcounter);
552         } else if (gctx->hindex != 0) {
553             ffc_params_set_h(ffc, gctx->hindex);
554         }
555         gctx->cb = osslcb;
556         gctx->cbarg = cbarg;
557         gencb = BN_GENCB_new();
558         if (gencb != NULL)
559             BN_GENCB_set(gencb, dh_gencb, genctx);
560
561         if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
562             /*
563              * NOTE: The old safe prime generator code is not used in fips mode,
564              * (i.e internally it ignores the generator and chooses a named
565              * group based on pbits.
566              */
567             if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR)
568                 ret = DH_generate_parameters_ex(dh, gctx->pbits,
569                                                 gctx->generator, gencb);
570             else
571                 ret = dh_generate_ffc_parameters(dh, gctx->gen_type, gctx->pbits,
572                                                  gctx->qbits, gctx->md, gencb);
573             if (ret <= 0)
574                 goto end;
575         }
576     }
577
578     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
579         if (ffc->p == NULL || ffc->g == NULL)
580             goto end;
581         if (gctx->priv_len > 0)
582             DH_set_length(dh, (long)gctx->priv_len);
583         if (DH_generate_key(dh) <= 0)
584             goto end;
585     }
586     ret = 1;
587 end:
588     if (ret <= 0) {
589         DH_free(dh);
590         dh = NULL;
591     }
592     BN_GENCB_free(gencb);
593     return dh;
594 }
595
596 static void dh_gen_cleanup(void *genctx)
597 {
598     struct dh_gen_ctx *gctx = genctx;
599
600     if (gctx == NULL)
601         return;
602
603     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
604     EVP_MD_free(gctx->md);
605     OPENSSL_free(gctx);
606 }
607
608 const OSSL_DISPATCH dh_keymgmt_functions[] = {
609     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
610     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
611     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
612     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params },
613     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
614       (void (*)(void))dh_gen_settable_params },
615     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
616     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
617     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
618     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
619     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
620     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
621     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
622     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
623     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
624     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
625     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
626     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
627     { 0, NULL }
628 };