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