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