1 /*
2  * Copyright 2019-2024 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 #include "internal/common.h"
16 
17 #include <string.h> /* strcmp */
18 #include <openssl/core_dispatch.h>
19 #include <openssl/core_names.h>
20 #include <openssl/bn.h>
21 #include <openssl/err.h>
22 #include "prov/implementations.h"
23 #include "prov/providercommon.h"
24 #include "prov/provider_ctx.h"
25 #include "crypto/dh.h"
26 #include "internal/sizes.h"
27 
28 static OSSL_FUNC_keymgmt_new_fn dh_newdata;
29 static OSSL_FUNC_keymgmt_free_fn dh_freedata;
30 static OSSL_FUNC_keymgmt_gen_init_fn dh_gen_init;
31 static OSSL_FUNC_keymgmt_gen_init_fn dhx_gen_init;
32 static OSSL_FUNC_keymgmt_gen_set_template_fn dh_gen_set_template;
33 static OSSL_FUNC_keymgmt_gen_set_params_fn dh_gen_set_params;
34 static OSSL_FUNC_keymgmt_gen_settable_params_fn dh_gen_settable_params;
35 static OSSL_FUNC_keymgmt_gen_fn dh_gen;
36 static OSSL_FUNC_keymgmt_gen_cleanup_fn dh_gen_cleanup;
37 static OSSL_FUNC_keymgmt_load_fn dh_load;
38 static OSSL_FUNC_keymgmt_get_params_fn dh_get_params;
39 static OSSL_FUNC_keymgmt_gettable_params_fn dh_gettable_params;
40 static OSSL_FUNC_keymgmt_set_params_fn dh_set_params;
41 static OSSL_FUNC_keymgmt_settable_params_fn dh_settable_params;
42 static OSSL_FUNC_keymgmt_has_fn dh_has;
43 static OSSL_FUNC_keymgmt_match_fn dh_match;
44 static OSSL_FUNC_keymgmt_validate_fn dh_validate;
45 static OSSL_FUNC_keymgmt_import_fn dh_import;
46 static OSSL_FUNC_keymgmt_import_types_fn dh_import_types;
47 static OSSL_FUNC_keymgmt_export_fn dh_export;
48 static OSSL_FUNC_keymgmt_export_types_fn dh_export_types;
49 static OSSL_FUNC_keymgmt_dup_fn dh_dup;
50 
51 #define DH_POSSIBLE_SELECTIONS                                                 \
52     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)
53 
54 struct dh_gen_ctx {
55     OSSL_LIB_CTX *libctx;
56 
57     FFC_PARAMS *ffc_params;
58     int selection;
59     /* All these parameters are used for parameter generation only */
60     /* If there is a group name then the remaining parameters are not needed */
61     int group_nid;
62     size_t pbits;
63     size_t qbits;
64     unsigned char *seed; /* optional FIPS186-4 param for testing */
65     size_t seedlen;
66     int gindex; /* optional  FIPS186-4 generator index (ignored if -1) */
67     int gen_type; /* see dhtype2id */
68     int generator; /* Used by DH_PARAMGEN_TYPE_GENERATOR in non fips mode only */
69     int pcounter;
70     int hindex;
71     int priv_len;
72 
73     char *mdname;
74     char *mdprops;
75     OSSL_CALLBACK *cb;
76     void *cbarg;
77     int dh_type;
78 };
79 
dh_gen_type_name2id_w_default(const char * name,int type)80 static int dh_gen_type_name2id_w_default(const char *name, int type)
81 {
82     if (strcmp(name, "default") == 0) {
83 #ifdef FIPS_MODULE
84         if (type == DH_FLAG_TYPE_DHX)
85             return DH_PARAMGEN_TYPE_FIPS_186_4;
86 
87         return DH_PARAMGEN_TYPE_GROUP;
88 #else
89         if (type == DH_FLAG_TYPE_DHX)
90             return DH_PARAMGEN_TYPE_FIPS_186_2;
91 
92         return DH_PARAMGEN_TYPE_GENERATOR;
93 #endif
94     }
95 
96     return ossl_dh_gen_type_name2id(name, type);
97 }
98 
dh_newdata(void * provctx)99 static void *dh_newdata(void *provctx)
100 {
101     DH *dh = NULL;
102 
103     if (ossl_prov_is_running()) {
104         dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));
105         if (dh != NULL) {
106             DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
107             DH_set_flags(dh, DH_FLAG_TYPE_DH);
108         }
109     }
110     return dh;
111 }
112 
dhx_newdata(void * provctx)113 static void *dhx_newdata(void *provctx)
114 {
115     DH *dh = NULL;
116 
117     dh = ossl_dh_new_ex(PROV_LIBCTX_OF(provctx));
118     if (dh != NULL) {
119         DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
120         DH_set_flags(dh, DH_FLAG_TYPE_DHX);
121     }
122     return dh;
123 }
124 
dh_freedata(void * keydata)125 static void dh_freedata(void *keydata)
126 {
127     DH_free(keydata);
128 }
129 
dh_has(const void * keydata,int selection)130 static int dh_has(const void *keydata, int selection)
131 {
132     const DH *dh = keydata;
133     int ok = 1;
134 
135     if (!ossl_prov_is_running() || dh == NULL)
136         return 0;
137     if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
138         return 1; /* the selection is not missing */
139 
140     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
141         ok = ok && (DH_get0_pub_key(dh) != NULL);
142     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
143         ok = ok && (DH_get0_priv_key(dh) != NULL);
144     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
145         ok = ok && (DH_get0_p(dh) != NULL && DH_get0_g(dh) != NULL);
146     return ok;
147 }
148 
dh_match(const void * keydata1,const void * keydata2,int selection)149 static int dh_match(const void *keydata1, const void *keydata2, int selection)
150 {
151     const DH *dh1 = keydata1;
152     const DH *dh2 = keydata2;
153     int ok = 1;
154 
155     if (!ossl_prov_is_running())
156         return 0;
157 
158     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
159         int key_checked = 0;
160 
161         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
162             const BIGNUM *pa = DH_get0_pub_key(dh1);
163             const BIGNUM *pb = DH_get0_pub_key(dh2);
164 
165             if (pa != NULL && pb != NULL) {
166                 ok = ok && BN_cmp(pa, pb) == 0;
167                 key_checked = 1;
168             }
169         }
170         if (!key_checked
171             && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
172             const BIGNUM *pa = DH_get0_priv_key(dh1);
173             const BIGNUM *pb = DH_get0_priv_key(dh2);
174 
175             if (pa != NULL && pb != NULL) {
176                 ok = ok && BN_cmp(pa, pb) == 0;
177                 key_checked = 1;
178             }
179         }
180         ok = ok && key_checked;
181     }
182     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
183         FFC_PARAMS *dhparams1 = ossl_dh_get0_params((DH *)dh1);
184         FFC_PARAMS *dhparams2 = ossl_dh_get0_params((DH *)dh2);
185 
186         ok = ok && ossl_ffc_params_cmp(dhparams1, dhparams2, 1);
187     }
188     return ok;
189 }
190 
dh_import(void * keydata,int selection,const OSSL_PARAM params[])191 static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
192 {
193     DH *dh = keydata;
194     int ok = 1;
195 
196     if (!ossl_prov_is_running() || dh == NULL)
197         return 0;
198 
199     if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
200         return 0;
201 
202     /* a key without parameters is meaningless */
203     ok = ok && ossl_dh_params_fromdata(dh, params);
204 
205     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
206         int include_private =
207             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
208 
209         ok = ok && ossl_dh_key_fromdata(dh, params, include_private);
210     }
211 
212     return ok;
213 }
214 
dh_export(void * keydata,int selection,OSSL_CALLBACK * param_cb,void * cbarg)215 static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
216                      void *cbarg)
217 {
218     DH *dh = keydata;
219     OSSL_PARAM_BLD *tmpl = NULL;
220     OSSL_PARAM *params = NULL;
221     int ok = 1;
222 
223     if (!ossl_prov_is_running() || dh == NULL)
224         return 0;
225 
226     if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
227         return 0;
228 
229     tmpl = OSSL_PARAM_BLD_new();
230     if (tmpl == NULL)
231         return 0;
232 
233     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
234         ok = ok && ossl_dh_params_todata(dh, tmpl, NULL);
235 
236     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
237         int include_private =
238             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
239 
240         ok = ok && ossl_dh_key_todata(dh, tmpl, NULL, include_private);
241     }
242 
243     if (!ok || (params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL) {
244         ok = 0;
245         goto err;
246     }
247 
248     ok = param_cb(params, cbarg);
249     OSSL_PARAM_free(params);
250 err:
251     OSSL_PARAM_BLD_free(tmpl);
252     return ok;
253 }
254 
255 /* IMEXPORT = IMPORT + EXPORT */
256 
257 # define DH_IMEXPORTABLE_PARAMETERS                                            \
258     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, NULL, 0),                             \
259     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_Q, NULL, 0),                             \
260     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, NULL, 0),                             \
261     OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_COFACTOR, NULL, 0),                      \
262     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),                          \
263     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),                        \
264     OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),                               \
265     OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),                         \
266     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),                \
267     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0)
268 # define DH_IMEXPORTABLE_PUBLIC_KEY                                            \
269     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
270 # define DH_IMEXPORTABLE_PRIVATE_KEY                                           \
271     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
272 static const OSSL_PARAM dh_all_types[] = {
273     DH_IMEXPORTABLE_PARAMETERS,
274     DH_IMEXPORTABLE_PUBLIC_KEY,
275     DH_IMEXPORTABLE_PRIVATE_KEY,
276     OSSL_PARAM_END
277 };
278 static const OSSL_PARAM dh_parameter_types[] = {
279     DH_IMEXPORTABLE_PARAMETERS,
280     OSSL_PARAM_END
281 };
282 static const OSSL_PARAM dh_key_types[] = {
283     DH_IMEXPORTABLE_PUBLIC_KEY,
284     DH_IMEXPORTABLE_PRIVATE_KEY,
285     OSSL_PARAM_END
286 };
287 static const OSSL_PARAM *dh_types[] = {
288     NULL,                        /* Index 0 = none of them */
289     dh_parameter_types,          /* Index 1 = parameter types */
290     dh_key_types,                /* Index 2 = key types */
291     dh_all_types                 /* Index 3 = 1 + 2 */
292 };
293 
dh_imexport_types(int selection)294 static const OSSL_PARAM *dh_imexport_types(int selection)
295 {
296     int type_select = 0;
297 
298     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
299         type_select += 1;
300     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
301         type_select += 2;
302     return dh_types[type_select];
303 }
304 
dh_import_types(int selection)305 static const OSSL_PARAM *dh_import_types(int selection)
306 {
307     return dh_imexport_types(selection);
308 }
309 
dh_export_types(int selection)310 static const OSSL_PARAM *dh_export_types(int selection)
311 {
312     return dh_imexport_types(selection);
313 }
314 
dh_get_params(void * key,OSSL_PARAM params[])315 static ossl_inline int dh_get_params(void *key, OSSL_PARAM params[])
316 {
317     DH *dh = key;
318     OSSL_PARAM *p;
319 
320     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
321         && !OSSL_PARAM_set_int(p, DH_bits(dh)))
322         return 0;
323     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
324         && !OSSL_PARAM_set_int(p, DH_security_bits(dh)))
325         return 0;
326     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
327         && !OSSL_PARAM_set_int(p, DH_size(dh)))
328         return 0;
329     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) {
330         if (p->data_type != OSSL_PARAM_OCTET_STRING)
331             return 0;
332         p->return_size = ossl_dh_key2buf(dh, (unsigned char **)&p->data,
333                                          p->data_size, 0);
334         if (p->return_size == 0)
335             return 0;
336     }
337 
338     return ossl_dh_params_todata(dh, NULL, params)
339         && ossl_dh_key_todata(dh, NULL, params, 1);
340 }
341 
342 static const OSSL_PARAM dh_params[] = {
343     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
344     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
345     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
346     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
347     DH_IMEXPORTABLE_PARAMETERS,
348     DH_IMEXPORTABLE_PUBLIC_KEY,
349     DH_IMEXPORTABLE_PRIVATE_KEY,
350     OSSL_PARAM_END
351 };
352 
dh_gettable_params(void * provctx)353 static const OSSL_PARAM *dh_gettable_params(void *provctx)
354 {
355     return dh_params;
356 }
357 
358 static const OSSL_PARAM dh_known_settable_params[] = {
359     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
360     OSSL_PARAM_END
361 };
362 
dh_settable_params(void * provctx)363 static const OSSL_PARAM *dh_settable_params(void *provctx)
364 {
365     return dh_known_settable_params;
366 }
367 
dh_set_params(void * key,const OSSL_PARAM params[])368 static int dh_set_params(void *key, const OSSL_PARAM params[])
369 {
370     DH *dh = key;
371     const OSSL_PARAM *p;
372 
373     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
374     if (p != NULL
375             && (p->data_type != OSSL_PARAM_OCTET_STRING
376                 || !ossl_dh_buf2key(dh, p->data, p->data_size)))
377         return 0;
378 
379     return 1;
380 }
381 
dh_validate_public(const DH * dh,int checktype)382 static int dh_validate_public(const DH *dh, int checktype)
383 {
384     const BIGNUM *pub_key = NULL;
385     int res = 0;
386 
387     DH_get0_key(dh, &pub_key, NULL);
388     if (pub_key == NULL)
389         return 0;
390 
391     /*
392      * The partial test is only valid for named group's with q = (p - 1) / 2
393      * but for that case it is also fully sufficient to check the key validity.
394      */
395     if (ossl_dh_is_named_safe_prime_group(dh))
396         return ossl_dh_check_pub_key_partial(dh, pub_key, &res);
397 
398     return DH_check_pub_key_ex(dh, pub_key);
399 }
400 
dh_validate_private(const DH * dh)401 static int dh_validate_private(const DH *dh)
402 {
403     int status = 0;
404     const BIGNUM *priv_key = NULL;
405 
406     DH_get0_key(dh, NULL, &priv_key);
407     if (priv_key == NULL)
408         return 0;
409     return ossl_dh_check_priv_key(dh, priv_key, &status);
410 }
411 
dh_validate(const void * keydata,int selection,int checktype)412 static int dh_validate(const void *keydata, int selection, int checktype)
413 {
414     const DH *dh = keydata;
415     int ok = 1;
416 
417     if (!ossl_prov_is_running())
418         return 0;
419 
420     if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
421         return 1; /* nothing to validate */
422 
423     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
424         /*
425          * Both of these functions check parameters. DH_check_params_ex()
426          * performs a lightweight check (e.g. it does not check that p is a
427          * safe prime)
428          */
429         if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
430             ok = ok && DH_check_params_ex(dh);
431         else
432             ok = ok && DH_check_ex(dh);
433     }
434 
435     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
436         ok = ok && dh_validate_public(dh, checktype);
437 
438     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
439         ok = ok && dh_validate_private(dh);
440 
441     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
442             == OSSL_KEYMGMT_SELECT_KEYPAIR)
443         ok = ok && ossl_dh_check_pairwise(dh);
444     return ok;
445 }
446 
dh_gen_init_base(void * provctx,int selection,const OSSL_PARAM params[],int type)447 static void *dh_gen_init_base(void *provctx, int selection,
448                               const OSSL_PARAM params[], int type)
449 {
450     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
451     struct dh_gen_ctx *gctx = NULL;
452 
453     if (!ossl_prov_is_running())
454         return NULL;
455 
456     if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
457                       | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)
458         return NULL;
459 
460     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
461         gctx->selection = selection;
462         gctx->libctx = libctx;
463         gctx->pbits = 2048;
464         gctx->qbits = 224;
465         gctx->mdname = NULL;
466 #ifdef FIPS_MODULE
467         gctx->gen_type = (type == DH_FLAG_TYPE_DHX)
468                          ? DH_PARAMGEN_TYPE_FIPS_186_4
469                          : DH_PARAMGEN_TYPE_GROUP;
470 #else
471         gctx->gen_type = (type == DH_FLAG_TYPE_DHX)
472                          ? DH_PARAMGEN_TYPE_FIPS_186_2
473                          : DH_PARAMGEN_TYPE_GENERATOR;
474 #endif
475         gctx->gindex = -1;
476         gctx->hindex = 0;
477         gctx->pcounter = -1;
478         gctx->generator = DH_GENERATOR_2;
479         gctx->dh_type = type;
480     }
481     if (!dh_gen_set_params(gctx, params)) {
482         OPENSSL_free(gctx);
483         gctx = NULL;
484     }
485     return gctx;
486 }
487 
dh_gen_init(void * provctx,int selection,const OSSL_PARAM params[])488 static void *dh_gen_init(void *provctx, int selection,
489                          const OSSL_PARAM params[])
490 {
491     return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DH);
492 }
493 
dhx_gen_init(void * provctx,int selection,const OSSL_PARAM params[])494 static void *dhx_gen_init(void *provctx, int selection,
495                           const OSSL_PARAM params[])
496 {
497    return dh_gen_init_base(provctx, selection, params, DH_FLAG_TYPE_DHX);
498 }
499 
dh_gen_set_template(void * genctx,void * templ)500 static int dh_gen_set_template(void *genctx, void *templ)
501 {
502     struct dh_gen_ctx *gctx = genctx;
503     DH *dh = templ;
504 
505     if (!ossl_prov_is_running() || gctx == NULL || dh == NULL)
506         return 0;
507     gctx->ffc_params = ossl_dh_get0_params(dh);
508     return 1;
509 }
510 
dh_set_gen_seed(struct dh_gen_ctx * gctx,unsigned char * seed,size_t seedlen)511 static int dh_set_gen_seed(struct dh_gen_ctx *gctx, unsigned char *seed,
512                            size_t seedlen)
513 {
514     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
515     gctx->seed = NULL;
516     gctx->seedlen = 0;
517     if (seed != NULL && seedlen > 0) {
518         gctx->seed = OPENSSL_memdup(seed, seedlen);
519         if (gctx->seed == NULL)
520             return 0;
521         gctx->seedlen = seedlen;
522     }
523     return 1;
524 }
525 
dh_gen_common_set_params(void * genctx,const OSSL_PARAM params[])526 static int dh_gen_common_set_params(void *genctx, const OSSL_PARAM params[])
527 {
528     struct dh_gen_ctx *gctx = genctx;
529     const OSSL_PARAM *p;
530     int gen_type = -1;
531 
532     if (gctx == NULL)
533         return 0;
534     if (ossl_param_is_empty(params))
535         return 1;
536 
537     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_TYPE);
538     if (p != NULL) {
539         if (p->data_type != OSSL_PARAM_UTF8_STRING
540             || ((gen_type =
541                  dh_gen_type_name2id_w_default(p->data, gctx->dh_type)) == -1)) {
542             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
543             return 0;
544         }
545         if (gen_type != -1)
546             gctx->gen_type = gen_type;
547     }
548     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
549     if (p != NULL) {
550         const DH_NAMED_GROUP *group = NULL;
551 
552         if (p->data_type != OSSL_PARAM_UTF8_STRING
553             || p->data == NULL
554             || (group = ossl_ffc_name_to_dh_named_group(p->data)) == NULL
555             || ((gctx->group_nid =
556                  ossl_ffc_named_group_get_uid(group)) == NID_undef)) {
557             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
558             return 0;
559         }
560     }
561     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PBITS)) != NULL
562         && !OSSL_PARAM_get_size_t(p, &gctx->pbits))
563         return 0;
564     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN);
565     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->priv_len))
566         return 0;
567     return 1;
568 }
569 
dh_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)570 static const OSSL_PARAM *dh_gen_settable_params(ossl_unused void *genctx,
571                                                 ossl_unused void *provctx)
572 {
573     static const OSSL_PARAM dh_gen_settable[] = {
574         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
575         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
576         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
577         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
578         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_GENERATOR, NULL),
579         OSSL_PARAM_END
580     };
581     return dh_gen_settable;
582 }
583 
dhx_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)584 static const OSSL_PARAM *dhx_gen_settable_params(ossl_unused void *genctx,
585                                                  ossl_unused void *provctx)
586 {
587     static const OSSL_PARAM dhx_gen_settable[] = {
588         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE, NULL, 0),
589         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
590         OSSL_PARAM_int(OSSL_PKEY_PARAM_DH_PRIV_LEN, NULL),
591         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, NULL),
592         OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_QBITS, NULL),
593         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST, NULL, 0),
594         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_FFC_DIGEST_PROPS, NULL, 0),
595         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_GINDEX, NULL),
596         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_FFC_SEED, NULL, 0),
597         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_PCOUNTER, NULL),
598         OSSL_PARAM_int(OSSL_PKEY_PARAM_FFC_H, NULL),
599         OSSL_PARAM_END
600     };
601     return dhx_gen_settable;
602 }
603 
dhx_gen_set_params(void * genctx,const OSSL_PARAM params[])604 static int dhx_gen_set_params(void *genctx, const OSSL_PARAM params[])
605 {
606     struct dh_gen_ctx *gctx = genctx;
607     const OSSL_PARAM *p;
608 
609     if (!dh_gen_common_set_params(genctx, params))
610         return 0;
611 
612     /* Parameters related to fips186-4 and fips186-2 */
613     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX);
614     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->gindex))
615         return 0;
616     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER);
617     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->pcounter))
618         return 0;
619     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H);
620     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->hindex))
621         return 0;
622     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED);
623     if (p != NULL
624         && (p->data_type != OSSL_PARAM_OCTET_STRING
625             || !dh_set_gen_seed(gctx, p->data, p->data_size)))
626             return 0;
627     if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS)) != NULL
628         && !OSSL_PARAM_get_size_t(p, &gctx->qbits))
629         return 0;
630     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
631     if (p != NULL) {
632         if (p->data_type != OSSL_PARAM_UTF8_STRING)
633             return 0;
634         OPENSSL_free(gctx->mdname);
635         gctx->mdname = OPENSSL_strdup(p->data);
636         if (gctx->mdname == NULL)
637             return 0;
638     }
639     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
640     if (p != NULL) {
641         if (p->data_type != OSSL_PARAM_UTF8_STRING)
642             return 0;
643         OPENSSL_free(gctx->mdprops);
644         gctx->mdprops = OPENSSL_strdup(p->data);
645         if (gctx->mdprops == NULL)
646             return 0;
647     }
648 
649     /* Parameters that are not allowed for DHX */
650     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);
651     if (p != NULL) {
652         ERR_raise(ERR_LIB_PROV, ERR_R_UNSUPPORTED);
653         return 0;
654     }
655     return 1;
656 }
657 
dh_gen_set_params(void * genctx,const OSSL_PARAM params[])658 static int dh_gen_set_params(void *genctx, const OSSL_PARAM params[])
659 {
660     struct dh_gen_ctx *gctx = genctx;
661     const OSSL_PARAM *p;
662 
663     if (!dh_gen_common_set_params(genctx, params))
664         return 0;
665 
666     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_GENERATOR);
667     if (p != NULL && !OSSL_PARAM_get_int(p, &gctx->generator))
668         return 0;
669 
670     /* Parameters that are not allowed for DH */
671     if (OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_GINDEX) != NULL
672         || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_PCOUNTER) != NULL
673         || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_H) != NULL
674         || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_SEED) != NULL
675         || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_QBITS) != NULL
676         || OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST) != NULL
677         || OSSL_PARAM_locate_const(params,
678                                    OSSL_PKEY_PARAM_FFC_DIGEST_PROPS) != NULL) {
679         ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
680         return 0;
681     }
682     return 1;
683 }
684 
dh_gencb(int p,int n,BN_GENCB * cb)685 static int dh_gencb(int p, int n, BN_GENCB *cb)
686 {
687     struct dh_gen_ctx *gctx = BN_GENCB_get_arg(cb);
688     OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
689 
690     params[0] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_POTENTIAL, &p);
691     params[1] = OSSL_PARAM_construct_int(OSSL_GEN_PARAM_ITERATION, &n);
692 
693     return gctx->cb(params, gctx->cbarg);
694 }
695 
dh_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)696 static void *dh_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
697 {
698     int ret = 0;
699     struct dh_gen_ctx *gctx = genctx;
700     DH *dh = NULL;
701     BN_GENCB *gencb = NULL;
702     FFC_PARAMS *ffc;
703 
704     if (!ossl_prov_is_running() || gctx == NULL)
705         return NULL;
706 
707     /*
708      * If a group name is selected then the type is group regardless of what
709      * the user selected. This overrides rather than errors for backwards
710      * compatibility.
711      */
712     if (gctx->group_nid != NID_undef)
713         gctx->gen_type = DH_PARAMGEN_TYPE_GROUP;
714 
715     /*
716      * Do a bounds check on context gen_type. Must be in range:
717      * DH_PARAMGEN_TYPE_GENERATOR <= gen_type <= DH_PARAMGEN_TYPE_GROUP
718      * Noted here as this needs to be adjusted if a new group type is
719      * added.
720      */
721     if (!ossl_assert((gctx->gen_type >= DH_PARAMGEN_TYPE_GENERATOR)
722                     && (gctx->gen_type <= DH_PARAMGEN_TYPE_GROUP))) {
723         ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
724                        "gen_type set to unsupported value %d", gctx->gen_type);
725         return NULL;
726     }
727 
728     /* For parameter generation - If there is a group name just create it */
729     if (gctx->gen_type == DH_PARAMGEN_TYPE_GROUP
730             && gctx->ffc_params == NULL) {
731         /* Select a named group if there is not one already */
732         if (gctx->group_nid == NID_undef)
733             gctx->group_nid = ossl_dh_get_named_group_uid_from_size(gctx->pbits);
734         if (gctx->group_nid == NID_undef)
735             return NULL;
736         dh = ossl_dh_new_by_nid_ex(gctx->libctx, gctx->group_nid);
737         if (dh == NULL)
738             return NULL;
739         ffc = ossl_dh_get0_params(dh);
740     } else {
741         dh = ossl_dh_new_ex(gctx->libctx);
742         if (dh == NULL)
743             return NULL;
744         ffc = ossl_dh_get0_params(dh);
745 
746         /* Copy the template value if one was passed */
747         if (gctx->ffc_params != NULL
748             && !ossl_ffc_params_copy(ffc, gctx->ffc_params))
749             goto end;
750 
751         if (!ossl_ffc_params_set_seed(ffc, gctx->seed, gctx->seedlen))
752             goto end;
753         if (gctx->gindex != -1) {
754             ossl_ffc_params_set_gindex(ffc, gctx->gindex);
755             if (gctx->pcounter != -1)
756                 ossl_ffc_params_set_pcounter(ffc, gctx->pcounter);
757         } else if (gctx->hindex != 0) {
758             ossl_ffc_params_set_h(ffc, gctx->hindex);
759         }
760         if (gctx->mdname != NULL)
761             ossl_ffc_set_digest(ffc, gctx->mdname, gctx->mdprops);
762         gctx->cb = osslcb;
763         gctx->cbarg = cbarg;
764         gencb = BN_GENCB_new();
765         if (gencb != NULL)
766             BN_GENCB_set(gencb, dh_gencb, genctx);
767 
768         if ((gctx->selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
769             /*
770              * NOTE: The old safe prime generator code is not used in fips mode,
771              * (i.e internally it ignores the generator and chooses a named
772              * group based on pbits.
773              */
774             if (gctx->gen_type == DH_PARAMGEN_TYPE_GENERATOR)
775                 ret = DH_generate_parameters_ex(dh, gctx->pbits,
776                                                 gctx->generator, gencb);
777             else
778                 ret = ossl_dh_generate_ffc_parameters(dh, gctx->gen_type,
779                                                       gctx->pbits, gctx->qbits,
780                                                       gencb);
781             if (ret <= 0)
782                 goto end;
783         }
784     }
785 
786     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
787         if (ffc->p == NULL || ffc->g == NULL)
788             goto end;
789         if (gctx->priv_len > 0)
790             DH_set_length(dh, (long)gctx->priv_len);
791         ossl_ffc_params_enable_flags(ffc, FFC_PARAM_FLAG_VALIDATE_LEGACY,
792                                      gctx->gen_type == DH_PARAMGEN_TYPE_FIPS_186_2);
793         if (DH_generate_key(dh) <= 0)
794             goto end;
795     }
796     DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
797     DH_set_flags(dh, gctx->dh_type);
798 
799     ret = 1;
800 end:
801     if (ret <= 0) {
802         DH_free(dh);
803         dh = NULL;
804     }
805     BN_GENCB_free(gencb);
806     return dh;
807 }
808 
dh_gen_cleanup(void * genctx)809 static void dh_gen_cleanup(void *genctx)
810 {
811     struct dh_gen_ctx *gctx = genctx;
812 
813     if (gctx == NULL)
814         return;
815 
816     OPENSSL_free(gctx->mdname);
817     OPENSSL_free(gctx->mdprops);
818     OPENSSL_clear_free(gctx->seed, gctx->seedlen);
819     OPENSSL_free(gctx);
820 }
821 
dh_load(const void * reference,size_t reference_sz)822 static void *dh_load(const void *reference, size_t reference_sz)
823 {
824     DH *dh = NULL;
825 
826     if (ossl_prov_is_running() && reference_sz == sizeof(dh)) {
827         /* The contents of the reference is the address to our object */
828         dh = *(DH **)reference;
829         /* We grabbed, so we detach it */
830         *(DH **)reference = NULL;
831         return dh;
832     }
833     return NULL;
834 }
835 
dh_dup(const void * keydata_from,int selection)836 static void *dh_dup(const void *keydata_from, int selection)
837 {
838     if (ossl_prov_is_running())
839         return ossl_dh_dup(keydata_from, selection);
840     return NULL;
841 }
842 
843 const OSSL_DISPATCH ossl_dh_keymgmt_functions[] = {
844     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dh_newdata },
845     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dh_gen_init },
846     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
847     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dh_gen_set_params },
848     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
849       (void (*)(void))dh_gen_settable_params },
850     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
851     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
852     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },
853     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
854     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
855     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
856     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },
857     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },
858     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
859     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
860     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
861     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
862     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
863     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
864     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
865     { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
866     OSSL_DISPATCH_END
867 };
868 
869 /* For any DH key, we use the "DH" algorithms regardless of sub-type. */
dhx_query_operation_name(int operation_id)870 static const char *dhx_query_operation_name(int operation_id)
871 {
872     return "DH";
873 }
874 
875 const OSSL_DISPATCH ossl_dhx_keymgmt_functions[] = {
876     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dhx_newdata },
877     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))dhx_gen_init },
878     { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE, (void (*)(void))dh_gen_set_template },
879     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))dhx_gen_set_params },
880     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
881       (void (*)(void))dhx_gen_settable_params },
882     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))dh_gen },
883     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))dh_gen_cleanup },
884     { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))dh_load },
885     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dh_freedata },
886     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
887     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
888     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))dh_set_params },
889     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))dh_settable_params },
890     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
891     { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
892     { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))dh_validate },
893     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
894     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
895     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
896     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))dh_export_types },
897     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
898       (void (*)(void))dhx_query_operation_name },
899     { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))dh_dup },
900     OSSL_DISPATCH_END
901 };
902