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